Ver Fonte

Merge branch 'master' into dynamic-bones

lviguier há 7 meses atrás
pai
commit
107921e150

+ 13 - 16
h3d/pass/CascadeShadowMap.hx

@@ -252,15 +252,18 @@ class CascadeShadowMap extends DirShadowMap {
 		return getCascadeProj(currentCascadeIndex);
 		return getCascadeProj(currentCascadeIndex);
 	}
 	}
 
 
-	inline function cullPassesSize( passes : h3d.pass.PassList, frustum : h3d.col.Frustum, minSize : Float ) {
-		passes.filter(function(p) {
-			var mb = Std.downcast(p.obj, h3d.scene.MeshBatch);
-			var col = p.obj.cullingCollider;
-			return if( mb != null && @:privateAccess mb.instanced.primitive.getBounds().dimension() < minSize ) false;
-				else if( col == null ) true;
-				else if ( col.dimension() < minSize ) false;
-				else col.inFrustum(frustum);
-		});
+	public dynamic function customCullPasses(passes : h3d.pass.PassList, frustum : h3d.col.Frustum, i : Int, minSize : Float) {
+		if ( minSize > 0.0 && i > 0 ) {
+			passes.filter(function(p) {
+				var mb = Std.downcast(p.obj, h3d.scene.MeshBatch);
+				var col = p.obj.cullingCollider;
+				return if( mb != null && @:privateAccess mb.instanced.primitive.getBounds().dimension() < minSize ) false;
+					else if( col == null ) true;
+					else if ( col.dimension() < minSize ) false;
+					else col.inFrustum(frustum);
+			});
+		} else
+			cullPasses(passes, function(col) return col.inFrustum(lightCamera.frustum));
 	}
 	}
 
 
 	override function draw( passes, ?sort ) {
 	override function draw( passes, ?sort ) {
@@ -312,15 +315,9 @@ class CascadeShadowMap extends DirShadowMap {
 			var lc = lightCameras[i];
 			var lc = lightCameras[i];
 			var dimension = Math.max(lc.orthoBounds.xMax - lc.orthoBounds.xMin,	lc.orthoBounds.yMax - lc.orthoBounds.yMin);
 			var dimension = Math.max(lc.orthoBounds.xMax - lc.orthoBounds.xMin,	lc.orthoBounds.yMax - lc.orthoBounds.yMin);
 			dimension = ( dimension * hxd.Math.clamp(minPixelSize, 0, size) ) / size;
 			dimension = ( dimension * hxd.Math.clamp(minPixelSize, 0, size) ) / size;
-			// first cascade draw all objects
-			if ( i == 0 )
-				dimension = 0.0;
 			lightCamera.orthoBounds = lc.orthoBounds;
 			lightCamera.orthoBounds = lc.orthoBounds;
 			lightCamera.update();
 			lightCamera.update();
-			if ( dimension > 0.0 )
-				cullPassesSize(passes, lightCamera.frustum, dimension);
-			else
-				cullPasses(passes, function(col) return col.inFrustum(lightCamera.frustum));
+			customCullPasses(passes, lightCamera.frustum, i, dimension);
 			textures[i] = processShadowMap( passes, texture, sort);
 			textures[i] = processShadowMap( passes, texture, sort);
 			passes.load(p);
 			passes.load(p);
 		}
 		}

+ 93 - 39
h3d/prim/ModelDatabase.hx

@@ -2,69 +2,100 @@ package h3d.prim;
 
 
 class ModelDatabase {
 class ModelDatabase {
 
 
-	public static var db : Map<String,{ v : Dynamic }> = new Map();
+	public static var db : Map<String, Dynamic> = new Map();
+	var baseDir(get, never) : String;
 
 
-	static var defaultLodConfigs : Map<String, Array<Float>> = new Map();
-	static var baseLodConfig = [ 0.5, 0.2, 0.01];
+	static var FILE_NAME = "model.props";
 
 
-	static var filename = "model.props";
+	static var LOD_CONFIG = "lodConfig";
+	static var DYN_BONES_CONFIG = "dynamicBones";
 
 
-	var baseDir(get, never) : String;
+	static var defaultLodConfigs : Map<String, Array<Float>> = new Map();
+	static var baseLodConfig = [ 0.5, 0.2, 0.01];
 
 
-	public function new() {
+	function new() {
 	}
 	}
 
 
 	function get_baseDir() return '';
 	function get_baseDir() return '';
-	function getFilePath( model : hxd.res.Resource ) {
-		var dir = model.entry.directory;
-		return dir == null || dir == "" ? filename : model.entry.directory + "/" + filename;
+
+	function getFilePath( directory : String ) {
+		return directory == null || directory == "" ? FILE_NAME : directory + "/" + FILE_NAME;
 	}
 	}
 
 
-	public function getModelData( model : hxd.res.Resource ) {
-		if( model == null )
+
+	function getRootData( directory : String ) {
+		if( directory == null )
 			return null;
 			return null;
-		var cached = ModelDatabase.db.get(model.entry.directory);
+		var cached = ModelDatabase.db.get(directory);
 		if( cached != null )
 		if( cached != null )
-			return cached.v;
-		var file = getFilePath(model);
+			return cached;
+		var file = getFilePath(directory);
 		var value = try haxe.Json.parse(hxd.res.Loader.currentInstance.load(file).toText()) catch( e : hxd.res.NotFound ) {};
 		var value = try haxe.Json.parse(hxd.res.Loader.currentInstance.load(file).toText()) catch( e : hxd.res.NotFound ) {};
-		ModelDatabase.db.set(model.entry.directory, { v : value });
+		ModelDatabase.db.set(directory, value);
 		return value;
 		return value;
 	}
 	}
 
 
-	function saveData( model : hxd.res.Resource, data : Dynamic ) {
-		var file = getFilePath(model);
+	function getModelData( directory : String, key : String ) {
+		var rootData = getRootData(directory);
+		cleanOldModelData(rootData, key);
+		return Reflect.field(rootData, key);
+	}
+
+	function saveModelData( directory : String, key : String, data : Dynamic ) {
+		var file = getFilePath(directory);
+
+		var rootData = getRootData(directory);
+		if (data == null || Reflect.fields(data).length == 0)
+			Reflect.deleteField(rootData, key);
+		else
+			Reflect.setField(rootData, key, data);
+
 		#if ((sys || nodejs) && !usesys)
 		#if ((sys || nodejs) && !usesys)
 		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
 		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
 		if( fs != null && !haxe.io.Path.isAbsolute(file) )
 		if( fs != null && !haxe.io.Path.isAbsolute(file) )
 			file = fs.baseDir + file;
 			file = fs.baseDir + file;
-		if( data == null || Reflect.fields(data).length == 0 )
+		if( rootData == null || Reflect.fields(rootData).length == 0 )
 			(try sys.FileSystem.deleteFile(file) catch( e : Dynamic ) {});
 			(try sys.FileSystem.deleteFile(file) catch( e : Dynamic ) {});
 		else
 		else
-			sys.io.File.saveContent(file, haxe.Json.stringify(data, "\t"));
+			sys.io.File.saveContent(file, haxe.Json.stringify(rootData, "\t"));
 		#else
 		#else
 		throw "Can't save model props database " + file;
 		throw "Can't save model props database " + file;
 		#end
 		#end
 	}
 	}
 
 
-	public function loadModelProps( name : String, hmd : HMDModel) {
-		var p : Dynamic = getModelData(@:privateAccess hmd.lib.resource);
 
 
-		var lodConfigs = Reflect.field(p, "lodConfig");
-		@:privateAccess hmd.lodConfig = Reflect.field(lodConfigs, name);
+	public function loadModelProps( objectName : String, hmd : HMDModel ) {
+		var key = @:privateAccess hmd.lib.resource.name + "/" + objectName;
+		var modelData : Dynamic = getModelData(@:privateAccess hmd.lib.resource.entry.directory, key);
+
+		loadLodConfig(modelData, hmd);
+		loadDynamicBonesConfig(modelData, hmd);
 	}
 	}
 
 
-	public function saveModelProps( name : String, hmd : HMDModel) {
-		var root : Dynamic = getModelData(@:privateAccess hmd.lib.resource);
-		if( root == null )
-			return;
+	public function saveModelProps( objectName : String, hmd : HMDModel ) {
+		var key = @:privateAccess hmd.lib.resource.name + "/" + objectName;
+		var data : Dynamic = getModelData(@:privateAccess hmd.lib.resource.entry.directory, key);
+		if( data == null )
+			data = {};
 
 
-		var lodConfigObj = Reflect.field(root, "lodConfig");
-		if (lodConfigObj == null) {
-			lodConfigObj = {};
-			Reflect.setField(root, "lodConfig", lodConfigObj);
-		}
+		saveLodConfig(data, hmd);
+		saveDynamicBonesConfig(data, hmd);
+
+		saveModelData(@:privateAccess hmd.lib.resource.entry.directory, @:privateAccess hmd.lib.resource.name + "/" + objectName, data);
+	}
 
 
+
+	function loadLodConfig( modelData : Dynamic, hmd : HMDModel ) {
+		var lodConfigs = Reflect.field(modelData, LOD_CONFIG);
+		@:privateAccess hmd.lodConfig = lodConfigs;
+	}
+
+	function loadDynamicBonesConfig( modelData : Dynamic, hmd : HMDModel ) {
+		// TODO
+	}
+
+
+	function saveLodConfig( data : Dynamic, hmd : HMDModel ) {
 		var isDefaultConfig = true;
 		var isDefaultConfig = true;
 		var defaultConfig = getDefaultLodConfig(@:privateAccess hmd.lib.resource.entry.directory);
 		var defaultConfig = getDefaultLodConfig(@:privateAccess hmd.lib.resource.entry.directory);
 
 
@@ -88,18 +119,18 @@ class ModelDatabase {
 				else
 				else
 					c[idx] = hmd.lodConfig[idx];
 					c[idx] = hmd.lodConfig[idx];
 			}
 			}
-			Reflect.setField(lodConfigObj, name, c);
+			Reflect.setField(data, LOD_CONFIG, c);
 		}
 		}
 		else
 		else
-			Reflect.deleteField(lodConfigObj, name);
-
-		if (Reflect.fields(lodConfigObj).length <= 0)
-			Reflect.deleteField(root, "lodConfig");
+			Reflect.deleteField(data, LOD_CONFIG);
+	}
 
 
-		saveData(@:privateAccess hmd.lib.resource, root);
+	function saveDynamicBonesConfig( data : Dynamic, hmd : HMDModel ) {
+		// TODO
 	}
 	}
 
 
-	public function getDefaultLodConfig( dir : String ) : Array<Float> {
+
+	function getDefaultLodConfig( dir : String ) : Array<Float> {
 		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
 		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
 		if (fs == null)
 		if (fs == null)
 			return baseLodConfig;
 			return baseLodConfig;
@@ -118,5 +149,28 @@ class ModelDatabase {
 
 
 	}
 	}
 
 
+	// Used to clean previous version of modelDatabase, should be removed after some time
+	function cleanOldModelData( rootData : Dynamic, key : String) {
+		var oldLodConfig = Reflect.field(rootData, LOD_CONFIG);
+		if (oldLodConfig != null) {
+			for (f in Reflect.fields(oldLodConfig)) {
+				if (key.indexOf(f) < 0)
+					continue;
+
+				var c = Reflect.field(oldLodConfig, f);
+
+				var newData = { "lodConfig" : c };
+				Reflect.setField(rootData, key, newData);
+
+				// Remove old entry
+				Reflect.deleteField(oldLodConfig, f);
+				Reflect.setField(rootData, LOD_CONFIG, oldLodConfig);
+			}
+
+			if (oldLodConfig == null || Reflect.fields(oldLodConfig).length == 0)
+				Reflect.deleteField(rootData, LOD_CONFIG);
+		}
+	}
+
 	public static var current = new ModelDatabase();
 	public static var current = new ModelDatabase();
 }
 }

+ 4 - 0
h3d/shader/ColorSpaces.hx

@@ -43,5 +43,9 @@ class ColorSpaces extends hxsl.Shader {
 			var r = ycocg.g + b;
 			var r = ycocg.g + b;
 			return vec3(r, g, b);
 			return vec3(r, g, b);
 		}
 		}
+
+		function int2rgba( c : Int ) : Vec4 {
+			return vec4((c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, (c >> 24) & 0xFF) * (1.0 / float(0xFF));
+		}
     }
     }
 }
 }

+ 8 - 2
h3d/shader/SAO.hx

@@ -16,6 +16,7 @@ class SAO extends ScreenShader {
 		@range(1,10) @const(16) var numSpiralTurns : Int;
 		@range(1,10) @const(16) var numSpiralTurns : Int;
 		@const var useWorldUV : Bool;
 		@const var useWorldUV : Bool;
 		@const var USE_FADE : Bool = false;
 		@const var USE_FADE : Bool = false;
+		@const var USE_SCALABLE_BIAS : Bool = false;
 
 
 		@ignore @param var depthTexture : Channel;
 		@ignore @param var depthTexture : Channel;
 		@ignore @param var normalTexture : Channel3;
 		@ignore @param var normalTexture : Channel3;
@@ -43,13 +44,18 @@ class SAO extends ScreenShader {
 			var unitOffset = vec2(cos(angle), sin(angle));
 			var unitOffset = vec2(cos(angle), sin(angle));
 			var targetUV = uv + radiusSS * alpha * unitOffset * screenRatio;
 			var targetUV = uv + radiusSS * alpha * unitOffset * screenRatio;
 			var Q = getPosition(targetUV);
 			var Q = getPosition(targetUV);
+			var radius = sampleRadius;
+			if (USE_SCALABLE_BIAS) {
+				var vQ = Q * cameraView;
+				radius *= log(1.0 + vQ.z) + 1;
+			}
 			var v = Q - position;
 			var v = Q - position;
 
 
 			var vv = dot(v, v);
 			var vv = dot(v, v);
-			var vn = dot(v, normal) - (bias * sampleRadius);
+			var vn = dot(v, normal) - bias * radius;
 
 
 			// Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
 			// Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
-			var radius2 = sampleRadius * sampleRadius;
+			var radius2 = radius * radius;
 			var f = max(radius2 - vv, 0.0) / radius2;
 			var f = max(radius2 - vv, 0.0) / radius2;
 			var epsilon = 0.01;
 			var epsilon = 0.01;
 			return f * f * f * max(vn / (epsilon + vv), 0.0);
 			return f * f * f * max(vn / (epsilon + vv), 0.0);

+ 1 - 0
hxsl/Ast.hx

@@ -102,6 +102,7 @@ enum VarQualifier {
 	Borrow( source : String );
 	Borrow( source : String );
 	Sampler( name : String );
 	Sampler( name : String );
 	Final;
 	Final;
+	Flat;
 }
 }
 
 
 enum Prec {
 enum Prec {

+ 3 - 1
hxsl/Checker.hx

@@ -801,7 +801,7 @@ class Checker {
 					checkConst(e);
 					checkConst(e);
 					einit = e;
 					einit = e;
 				}
 				}
-				if( v.type == null ) error("Type required for variable declaration", e.pos);				
+				if( v.type == null ) error("Type required for variable declaration", e.pos);
 				if( isImport && v.kind == Param )
 				if( isImport && v.kind == Param )
 					continue;
 					continue;
 
 
@@ -874,6 +874,7 @@ class Checker {
 			name : v.name,
 			name : v.name,
 			kind : v.kind,
 			kind : v.kind,
 			type : v.type,
 			type : v.type,
+			qualifiers : v.qualifiers
 		};
 		};
 		if( parent != null )
 		if( parent != null )
 			tv.parent = parent;
 			tv.parent = parent;
@@ -932,6 +933,7 @@ class Checker {
 					default: error("Sampler should be on sampler type or sampler array", pos);
 					default: error("Sampler should be on sampler type or sampler array", pos);
 					}
 					}
 				case Ignore, Doc(_):
 				case Ignore, Doc(_):
+				case Flat: if( tv.kind != Local ) error("flat only allowed on local", pos);
 				}
 				}
 		}
 		}
 		if( tv.type != null )
 		if( tv.type != null )

+ 1 - 1
hxsl/Debug.hx

@@ -12,7 +12,7 @@ class Debug {
 	public static function varName( v : Ast.TVar, swizBits = 15 ) {
 	public static function varName( v : Ast.TVar, swizBits = 15 ) {
 		var name = v.name;
 		var name = v.name;
 		if( swizBits != 15 ) name += swizStr(swizBits);
 		if( swizBits != 15 ) name += swizStr(swizBits);
-		return VAR_IDS ? v.name+"@"+v.id : v.name;
+		return VAR_IDS ? name+"@"+v.id : name;
 	}
 	}
 
 
 	static function swizStr( bits : Int ) {
 	static function swizStr( bits : Int ) {

+ 1 - 0
hxsl/Flatten.hx

@@ -168,6 +168,7 @@ class Flatten {
 				name : v.name,
 				name : v.name,
 				type : TArray(TVec(4,VFloat),SConst(size)),
 				type : TArray(TVec(4,VFloat),SConst(size)),
 				kind : v.kind,
 				kind : v.kind,
+				qualifiers : v.qualifiers
 			};
 			};
 			var a = new Alloc(v2,VFloat,0,0);
 			var a = new Alloc(v2,VFloat,0,0);
 			a.v = v;
 			a.v = v;

+ 2 - 0
hxsl/GlslOut.hx

@@ -746,6 +746,8 @@ class GlslOut {
 		case Input:
 		case Input:
 			add( isES2 ? "attribute " : "in ");
 			add( isES2 ? "attribute " : "in ");
 		case Var:
 		case Var:
+			if ( Tools.hasQualifier(v, Flat) )
+				add("flat ");
 			add( isES2 ? "varying " : (isVertex ? "out " : "in "));
 			add( isES2 ? "varying " : (isVertex ? "out " : "in "));
 		case Output:
 		case Output:
 			if( isES2 ) {
 			if( isES2 ) {

+ 6 - 1
hxsl/Linker.hx

@@ -360,6 +360,10 @@ class Linker {
 			frag : [-1000],
 			frag : [-1000],
 			main : [-2500],
 			main : [-2500],
 		};
 		};
+		var shaderOffset = {
+			vert : -1500,
+			frag : -500,
+		}
 		for( s in shadersData ) {
 		for( s in shadersData ) {
 			for( f in s.funs ) {
 			for( f in s.funs ) {
 				var v = allocVar(f.ref, f.expr.p);
 				var v = allocVar(f.ref, f.expr.p);
@@ -368,7 +372,8 @@ class Linker {
 				case Vertex, Fragment:
 				case Vertex, Fragment:
 					if( mode == Compute )
 					if( mode == Compute )
 						throw "Unexpected "+v.kind.getName().toLowerCase()+"() function in compute shader";
 						throw "Unexpected "+v.kind.getName().toLowerCase()+"() function in compute shader";
-					addShader(s.name + "." + (v.kind == Vertex ? "vertex" : "fragment"), v.kind == Vertex, f.expr, priority);
+					var offset = v.kind == Vertex ? shaderOffset.vert : shaderOffset.frag;
+					addShader(s.name + "." + (v.kind == Vertex ? "vertex" : "fragment"), v.kind == Vertex, f.expr, priority + offset);
 				case Main:
 				case Main:
 					if( mode != Compute )
 					if( mode != Compute )
 						throw "Unexpected main() outside compute shader";
 						throw "Unexpected main() outside compute shader";

+ 2 - 0
hxsl/MacroParser.hx

@@ -78,6 +78,8 @@ class MacroParser {
 			v.qualifiers.push(Ignore);
 			v.qualifiers.push(Ignore);
 		case "perInstance":
 		case "perInstance":
 			v.qualifiers.push(PerInstance(1));
 			v.qualifiers.push(PerInstance(1));
+		case "flat":
+			v.qualifiers.push(Flat);
 		default:
 		default:
 			error("Unsupported qualifier " + m.name, m.pos);
 			error("Unsupported qualifier " + m.name, m.pos);
 		}
 		}

+ 1 - 0
hxsl/Printer.hx

@@ -65,6 +65,7 @@ class Printer {
 				case Borrow(s): "borrow(" + s + ")";
 				case Borrow(s): "borrow(" + s + ")";
 				case Sampler(s): "sampler("+ s + ")";
 				case Sampler(s): "sampler("+ s + ")";
 				case Final: "final";
 				case Final: "final";
+				case Flat: "flat";
 				}) + " ");
 				}) + " ");
 		}
 		}
 		if( v.kind != defKind )
 		if( v.kind != defKind )

+ 2 - 1
hxsl/Serializer.hx

@@ -209,7 +209,7 @@ class Serializer {
 			for( q in v.qualifiers ) {
 			for( q in v.qualifiers ) {
 				out.addByte(q.getIndex());
 				out.addByte(q.getIndex());
 				switch (q) {
 				switch (q) {
-				case Private, Nullable, PerObject, Shared, Ignore, Final:
+				case Private, Nullable, PerObject, Shared, Ignore, Final, Flat:
 				case Const(max): out.addInt32(max == null ? 0 : max);
 				case Const(max): out.addInt32(max == null ? 0 : max);
 				case Name(n): writeString(n);
 				case Name(n): writeString(n);
 				case Precision(p): out.addByte(p.getIndex());
 				case Precision(p): out.addByte(p.getIndex());
@@ -439,6 +439,7 @@ class Serializer {
 				case 11: Borrow(readString());
 				case 11: Borrow(readString());
 				case 12: Sampler(readString());
 				case 12: Sampler(readString());
 				case 13: Final;
 				case 13: Final;
+				case 14: Flat;
 				default: throw "assert";
 				default: throw "assert";
 				}
 				}
 				v.qualifiers.push(q);
 				v.qualifiers.push(q);

+ 11 - 2
hxsl/Splitter.hx

@@ -261,8 +261,17 @@ class Splitter {
 						kind : v.kind,
 						kind : v.kind,
 						type : v.type,
 						type : v.type,
 					};
 					};
-					if( v.qualifiers != null && v.qualifiers.indexOf(Final) >= 0 )
-						nv.qualifiers = [Final];
+					if( v.qualifiers != null ) {
+						for ( q in v.qualifiers ) {
+							switch (q) {
+							case Final, Flat:
+								if ( nv.qualifiers == null )
+									nv.qualifiers = [];
+								nv.qualifiers.push(q);
+							case Const(_), Private, Nullable, PerObject, Name(_), Shared, Precision(_), Range(_,_), Ignore, PerInstance(_), Doc(_), Borrow(_), Sampler(_):
+							}
+						}
+					}
 					uniqueName(nv);
 					uniqueName(nv);
 				}
 				}
 				varMap.set(v,nv);
 				varMap.set(v,nv);