Przeglądaj źródła

World: Add support for normal maps

trethaller 7 lat temu
rodzic
commit
e86a978dc1
1 zmienionych plików z 38 dodań i 4 usunięć
  1. 38 4
      h3d/scene/World.hx

+ 38 - 4
h3d/scene/World.hx

@@ -45,6 +45,7 @@ class WorldMaterial {
 	public var bits : Int;
 	public var bits : Int;
 	public var t : h3d.mat.BigTexture.BigTextureElement;
 	public var t : h3d.mat.BigTexture.BigTextureElement;
 	public var spec : h3d.mat.BigTexture.BigTextureElement;
 	public var spec : h3d.mat.BigTexture.BigTextureElement;
+	public var normal : h3d.mat.BigTexture.BigTextureElement;
 	public var mat : hxd.fmt.hmd.Data.Material;
 	public var mat : hxd.fmt.hmd.Data.Material;
 	public var culling : Bool;
 	public var culling : Bool;
 	public var blend : h3d.mat.BlendMode;
 	public var blend : h3d.mat.BlendMode;
@@ -60,7 +61,13 @@ class WorldMaterial {
 		shaders = [];
 		shaders = [];
 	}
 	}
 	public function updateBits() {
 	public function updateBits() {
-		bits = (t.t == null ? 0 : t.t.id << 8) | (blend.getIndex() << 5) | ((killAlpha == null ? 0 : 1) << 4) | ((lights ? 1 : 0) << 3) | ((shadows ? 1 : 0) << 2) | ((spec == null ? 0 : 1) << 1) | (culling ? 1 : 0);
+		bits = (t.t == null ? 0 : t.t.id    << 8)
+			| ((normal == null ? 0 : 1)     << 5)
+			| ((killAlpha == null ? 0 : 1)  << 4)
+			| ((lights ? 1 : 0)             << 3)
+			| ((shadows ? 1 : 0)            << 2)
+			| ((spec == null ? 0 : 1)       << 1)
+			| (culling ? 1 : 0);
 	}
 	}
 }
 }
 
 
@@ -101,6 +108,10 @@ class World extends Object {
 		For each texture loaded, will call resolveSpecularTexture and have separate spec texture.
 		For each texture loaded, will call resolveSpecularTexture and have separate spec texture.
 	*/
 	*/
 	public var enableSpecular = false;
 	public var enableSpecular = false;
+	/*
+		For each texture loaded, will call resolveNormalMap and have separate normal texture.
+	*/
+	public var enableNormals = false;
 	/*
 	/*
 		When enableSpecular=true, will store the specular value in the alpha channel instead of a different texture.
 		When enableSpecular=true, will store the specular value in the alpha channel instead of a different texture.
 		This will erase alpha value of transparent textures, so should only be used if specular is only on opaque models.
 		This will erase alpha value of transparent textures, so should only be used if specular is only on opaque models.
@@ -113,7 +124,7 @@ class World extends Object {
 	var soilColor = 0x408020;
 	var soilColor = 0x408020;
 	var chunks : Array<WorldChunk>;
 	var chunks : Array<WorldChunk>;
 	var allChunks : Array<WorldChunk>;
 	var allChunks : Array<WorldChunk>;
-	var bigTextures : Array<{ diffuse : h3d.mat.BigTexture, spec : h3d.mat.BigTexture }>;
+	var bigTextures : Array<{ diffuse : h3d.mat.BigTexture, spec : h3d.mat.BigTexture, normal : h3d.mat.BigTexture }>;
 	var textures : Map<String, WorldMaterial>;
 	var textures : Map<String, WorldMaterial>;
 
 
 	public function new( chunkSize : Int, worldSize : Int, ?parent, ?autoCollect = true ) {
 	public function new( chunkSize : Int, worldSize : Int, ?parent, ?autoCollect = true ) {
@@ -172,6 +183,10 @@ class World extends Object {
 		}
 		}
 	}
 	}
 
 
+	function resolveNormalMap( path : String ) : hxd.res.Image {
+		return null;
+	}
+
 	function loadMaterialTexture( r : hxd.res.Model, mat : hxd.fmt.hmd.Data.Material ) : WorldMaterial {
 	function loadMaterialTexture( r : hxd.res.Model, mat : hxd.fmt.hmd.Data.Material ) : WorldMaterial {
 		var texturePath = resolveTexturePath(r, mat.diffuseTexture);
 		var texturePath = resolveTexturePath(r, mat.diffuseTexture);
 		var m = textures.get(texturePath);
 		var m = textures.get(texturePath);
@@ -190,7 +205,7 @@ class World extends Object {
 		}
 		}
 		if( t == null ) {
 		if( t == null ) {
 			var b = new h3d.mat.BigTexture(bigTextures.length, bigTextureSize, bigTextureBG);
 			var b = new h3d.mat.BigTexture(bigTextures.length, bigTextureSize, bigTextureBG);
-			btex = { diffuse : b, spec : null };
+			btex = { diffuse : b, spec : null, normal : null };
 			bigTextures.unshift( btex );
 			bigTextures.unshift( btex );
 			t = b.add(rt);
 			t = b.add(rt);
 			if( t == null ) throw "Texture " + texturePath + " is too big";
 			if( t == null ) throw "Texture " + texturePath + " is too big";
@@ -214,9 +229,21 @@ class World extends Object {
 			}
 			}
 		}
 		}
 
 
+		var normalMap = null;
+		if( enableNormals ) {
+			var res = resolveNormalMap(texturePath);
+			if( btex.normal == null )
+				btex.normal = new h3d.mat.BigTexture(-1, bigTextureSize, bigTextureBG);
+			if( res != null )
+				normalMap = btex.normal.add(res);
+			else
+				@:privateAccess btex.normal.allocPos(t.t.tex.width, t.t.tex.height); // keep UV in-sync
+		}
+
 		var m = new WorldMaterial();
 		var m = new WorldMaterial();
 		m.t = t;
 		m.t = t;
 		m.spec = specTex;
 		m.spec = specTex;
+		m.normal = normalMap;
 		m.blend = getBlend(rt);
 		m.blend = getBlend(rt);
 		m.killAlpha = null;
 		m.killAlpha = null;
 		m.mat = mat;
 		m.mat = mat;
@@ -231,6 +258,8 @@ class World extends Object {
 			b.diffuse.done();
 			b.diffuse.done();
 			if(b.spec != null)
 			if(b.spec != null)
 				b.spec.done();
 				b.spec.done();
+			if(b.normal != null)
+				b.normal.done();
 		}
 		}
 	}
 	}
 
 
@@ -407,7 +436,8 @@ class World extends Object {
 		mesh.material.textureShader.killAlphaThreshold = mat.killAlpha;
 		mesh.material.textureShader.killAlphaThreshold = mat.killAlpha;
 		mesh.material.mainPass.enableLights = mat.lights;
 		mesh.material.mainPass.enableLights = mat.lights;
 		mesh.material.shadows = mat.shadows;
 		mesh.material.shadows = mat.shadows;
-		mesh.material.mainPass.culling = mat.culling ? Back : None;
+		mesh.material.mainPass.culling = Back;
+		mesh.material.mainPass.depthWrite = true;
 
 
 		for(s in mat.shaders)
 		for(s in mat.shaders)
 			mesh.material.mainPass.addShader(s);
 			mesh.material.mainPass.addShader(s);
@@ -420,6 +450,10 @@ class World extends Object {
 				mesh.material.specularTexture = mat.spec.t.tex;
 				mesh.material.specularTexture = mat.spec.t.tex;
 		} else
 		} else
 			mesh.material.specularAmount = 0;
 			mesh.material.specularAmount = 0;
+
+		if(mat.normal != null) {
+			mesh.material.normalMap = mat.normal.t.tex;
+		}
 	}
 	}
 
 
 	override function dispose() {
 	override function dispose() {