Browse Source

Update Terrain, add Tangent

ShiroSmith 5 years ago
parent
commit
e2b4630202

+ 9 - 4
hrt/prefab/terrain/Terrain.hx

@@ -329,12 +329,17 @@ class Terrain extends Object3D {
 		for( tile in terrain.tiles ) {
 		for( tile in terrain.tiles ) {
 			if( tile.grid == null || tile.grid.normals == null ) continue;
 			if( tile.grid == null || tile.grid.normals == null ) continue;
 			var normals = tile.grid.normals;
 			var normals = tile.grid.normals;
+			var tangents = tile.grid.tangents;
 			var fileName = tile.tileX + "_" + tile.tileY + "_" + "n";
 			var fileName = tile.tileX + "_" + tile.tileY + "_" + "n";
-			var bytes = haxe.io.Bytes.alloc(normals.length * 3 * 4);
+			var stride = 3 * 4 + 3 * 4; // Normal + Tangent
+			var bytes = haxe.io.Bytes.alloc(normals.length * stride);
 			for( i in 0 ... normals.length ) {
 			for( i in 0 ... normals.length ) {
-				bytes.setFloat(i*3*4, normals[i].x);
-				bytes.setFloat(i*3*4+4, normals[i].y);
-				bytes.setFloat(i*3*4+8, normals[i].z);
+				bytes.setFloat(i*stride, normals[i].x);
+				bytes.setFloat(i*stride+4, normals[i].y);
+				bytes.setFloat(i*stride+8, normals[i].z);
+				bytes.setFloat(i*stride+12, tangents[i].x);
+				bytes.setFloat(i*stride+16, tangents[i].y);
+				bytes.setFloat(i*stride+20, tangents[i].z);
 			}
 			}
 			ctx.shared.savePrefabDat(fileName, "bin", name, bytes);
 			ctx.shared.savePrefabDat(fileName, "bin", name, bytes);
 		}
 		}

+ 2 - 0
hrt/prefab/terrain/TerrainMesh.hx

@@ -164,6 +164,8 @@ class TerrainMesh extends h3d.scene.Object {
 		}
 		}
 		for( tile in tiles )
 		for( tile in tiles )
 			tile.blendEdges();
 			tile.blendEdges();
+		for( tile in tiles )
+			tile.computeTangents();
 	}
 	}
 
 
 	public function refreshAllTex() {
 	public function refreshAllTex() {

+ 20 - 9
hrt/prefab/terrain/Tile.hx

@@ -21,7 +21,7 @@ class Tile extends h3d.scene.Mesh {
 	// set by prefab loader for CPU access ingame
 	// set by prefab loader for CPU access ingame
 	public var packedWeightMapPixel : hxd.Pixels;
 	public var packedWeightMapPixel : hxd.Pixels;
 	public var indexMapPixels : hxd.Pixels;
 	public var indexMapPixels : hxd.Pixels;
-	public var normalBytes : haxe.io.Bytes;
+	public var normalTangentBytes : haxe.io.Bytes;
 
 
 	var heightmapPixels : hxd.Pixels.PixelsFloat;
 	var heightmapPixels : hxd.Pixels.PixelsFloat;
 	var shader : hrt.shader.Terrain;
 	var shader : hrt.shader.Terrain;
@@ -67,18 +67,22 @@ class Tile extends h3d.scene.Mesh {
 		return heightmapPixels;
 		return heightmapPixels;
 	}
 	}
 
 
-	public function createBigPrim( normals : haxe.io.Bytes ) {
+	public function createBigPrim( bytes : haxe.io.Bytes ) {
 		if( bigPrim != null ) bigPrim.dispose();
 		if( bigPrim != null ) bigPrim.dispose();
-		normalBytes = normals;
-		bigPrim = new h3d.prim.BigPrimitive(6);
-		var n = new h3d.Vector(0,0,0);
+		normalTangentBytes = bytes;
+		bigPrim = new h3d.prim.BigPrimitive(9, true);
+		var stride = 3 * 4 + 3 * 4; // Normal + Tangent
 		inline function addVertice(x : Float, y : Float, i : Int) {
 		inline function addVertice(x : Float, y : Float, i : Int) {
 			// Pos
 			// Pos
 			bigPrim.addPoint(x, y, getHeight(x / terrain.tileSize, y / terrain.tileSize)); // Use addPoint() instead of addVertexValue() for the bounds
 			bigPrim.addPoint(x, y, getHeight(x / terrain.tileSize, y / terrain.tileSize)); // Use addPoint() instead of addVertexValue() for the bounds
 			// Normal
 			// Normal
-			bigPrim.addVertexValue(normals.getFloat(i * 3 * 4));
-			bigPrim.addVertexValue(normals.getFloat(i * 3 * 4 + 4));
-			bigPrim.addVertexValue(normals.getFloat(i * 3 * 4 + 8));
+			bigPrim.addVertexValue(bytes.getFloat(i * stride));
+			bigPrim.addVertexValue(bytes.getFloat(i * stride + 4));
+			bigPrim.addVertexValue(bytes.getFloat(i * stride + 8));
+			// Tangents
+			bigPrim.addVertexValue(bytes.getFloat(i * stride + 12));
+			bigPrim.addVertexValue(bytes.getFloat(i * stride + 16));
+			bigPrim.addVertexValue(bytes.getFloat(i * stride + 20));
 		}
 		}
 
 
 		var cellCount = terrain.cellCount;
 		var cellCount = terrain.cellCount;
@@ -105,6 +109,11 @@ class Tile extends h3d.scene.Mesh {
 		primitive = bigPrim;
 		primitive = bigPrim;
 	}
 	}
 
 
+	public function computeTangents() {
+		if( grid != null )
+			grid.addTangents();
+	}
+
 	public function refreshGrid() {
 	public function refreshGrid() {
 		if( bigPrim != null )
 		if( bigPrim != null )
 			return;
 			return;
@@ -114,6 +123,7 @@ class Tile extends h3d.scene.Mesh {
 			primitive = grid;
 			primitive = grid;
 		}
 		}
 		computeNormals();
 		computeNormals();
+		computeTangents();
 	}
 	}
 
 
 	public function blendEdges() {
 	public function blendEdges() {
@@ -142,6 +152,7 @@ class Tile extends h3d.scene.Mesh {
 		computeEdgesHeight(flags);
 		computeEdgesHeight(flags);
 		computeNormals();
 		computeNormals();
 		computeEdgesNormals();
 		computeEdgesNormals();
+		computeTangents();
 	}
 	}
 
 
 	function refreshHeightMap() {
 	function refreshHeightMap() {
@@ -654,7 +665,7 @@ class Tile extends h3d.scene.Mesh {
 				}
 				}
 			}
 			}
 			if( needRealloc ) {
 			if( needRealloc ) {
-				createBigPrim(normalBytes);
+				createBigPrim(normalTangentBytes);
 				cachedBounds = null;
 				cachedBounds = null;
 			}
 			}
 		}
 		}

+ 22 - 8
hrt/shader/Terrain.hx

@@ -4,6 +4,7 @@ class Terrain extends hxsl.Shader {
 
 
 	static var SRC = {
 	static var SRC = {
 
 
+		@input var tangent : Vec3;
 		@:import h3d.shader.BaseMesh;
 		@:import h3d.shader.BaseMesh;
 		@const var SHOW_GRID : Bool;
 		@const var SHOW_GRID : Bool;
 		@const var SURFACE_COUNT : Int;
 		@const var SURFACE_COUNT : Int;
@@ -49,6 +50,7 @@ class Terrain extends hxsl.Shader {
 
 
 		var tangentViewPos : Vec3;
 		var tangentViewPos : Vec3;
 		var tangentFragPos : Vec3;
 		var tangentFragPos : Vec3;
+		var transformedTangent : Vec4;
 
 
 		function vertex() {
 		function vertex() {
 			calculatedUV = input.position.xy / primSize;
 			calculatedUV = input.position.xy / primSize;
@@ -57,7 +59,11 @@ class Terrain extends hxsl.Shader {
 				terrainUV += 0.5 / heightMapSize;
 				terrainUV += 0.5 / heightMapSize;
 				transformedPosition += (vec3(0,0, textureLod(heightMap, terrainUV, 0).r) * global.modelView.mat3());
 				transformedPosition += (vec3(0,0, textureLod(heightMap, terrainUV, 0).r) * global.modelView.mat3());
 			}
 			}
-			TBN = mat3(normalize(cross(transformedNormal, vec3(0,1,0))), normalize(cross(transformedNormal,vec3(-1,0,0))), transformedNormal);
+
+			transformedTangent = vec4(tangent * global.modelView.mat3(),tangent.dot(tangent) > 0.5 ? 1. : -1.);
+			var tanX = transformedTangent.xyz.normalize() * -transformedTangent.w;
+			var tanY = transformedNormal.cross(tanX).normalize();
+			TBN = mat3(tanX, tanY, transformedNormal);
 			tangentViewPos = camera.position * TBN;
 			tangentViewPos = camera.position * TBN;
 			tangentFragPos = transformedPosition * TBN;
 			tangentFragPos = transformedPosition * TBN;
 		}
 		}
@@ -84,11 +90,11 @@ class Terrain extends hxsl.Shader {
 			if( !PARALLAX )
 			if( !PARALLAX )
 				return uv;
 				return uv;
 			else {
 			else {
-				var viewDir = normalize(tangentViewPos - tangentFragPos);
-				var numLayers = mix(float(maxStep), float(minStep), viewDir.dot(transformedNormal));
+				var viewNS = normalize(tangentViewPos - tangentFragPos);
+				var numLayers = mix(float(maxStep), float(minStep), viewNS.dot(transformedNormal));
 				var layerDepth = 1 / numLayers;
 				var layerDepth = 1 / numLayers;
 				var curLayerDepth = 0.;
 				var curLayerDepth = 0.;
-				var delta = (viewDir.xy / viewDir.z) * parallaxAmount / numLayers;
+				var delta = (viewNS.xy / viewNS.z) * parallaxAmount / numLayers;
 				var curUV = uv;
 				var curUV = uv;
 				var depth = getDepth(i, curUV);
 				var depth = getDepth(i, curUV);
 				var curDepth = depth.dot(w);
 				var curDepth = depth.dot(w);
@@ -125,7 +131,11 @@ class Terrain extends hxsl.Shader {
 			if( CHECKER ) {
 			if( CHECKER ) {
 				var tile = abs(abs(floor(input.position.x)) % 2 - abs(floor(input.position.y)) % 2);
 				var tile = abs(abs(floor(input.position.x)) % 2 - abs(floor(input.position.y)) % 2);
 				pixelColor = vec4(mix(vec3(0.4), vec3(0.1), tile), 1.0);
 				pixelColor = vec4(mix(vec3(0.4), vec3(0.1), tile), 1.0);
-				transformedNormal = vec3(0,0,1) * TBN;
+				var n = transformedNormal;
+				var nf = vec3(0,0,1);
+				var tanX = transformedTangent.xyz;
+				var tanY = n.cross(tanX) * -transformedTangent.w;
+				transformedNormal = (nf.x * tanX + nf.y * tanY + nf.z * n).normalize();
 				roughnessValue = mix(0.1, 0.9, tile);
 				roughnessValue = mix(0.1, 0.9, tile);
 				metalnessValue = mix(1.0, 0, tile);
 				metalnessValue = mix(1.0, 0, tile);
 				occlusionValue = 1;
 				occlusionValue = 1;
@@ -136,7 +146,11 @@ class Terrain extends hxsl.Shader {
 				for(i in 0 ... SURFACE_COUNT)
 				for(i in 0 ... SURFACE_COUNT)
 					blendCount += ceil(weightTextures.get(vec3(calculatedUV, i)).r);
 					blendCount += ceil(weightTextures.get(vec3(calculatedUV, i)).r);
 				pixelColor = vec4(mix(vec3(0,1,0), vec3(1,0,0), blendCount / 3.0) , 1);
 				pixelColor = vec4(mix(vec3(0,1,0), vec3(1,0,0), blendCount / 3.0) , 1);
-				transformedNormal = vec3(0,0,1) * TBN;
+				var n = transformedNormal;
+				var nf = vec3(0,0,1);
+				var tanX = transformedTangent.xyz;
+				var tanY = n.cross(tanX) * -transformedTangent.w;
+				transformedNormal = (nf.x * tanX + nf.y * tanY + nf.z * n).normalize();
 				emissiveValue = 1;
 				emissiveValue = 1;
 				roughnessValue = 1;
 				roughnessValue = 1;
 				metalnessValue = 0;
 				metalnessValue = 0;
@@ -195,9 +209,9 @@ class Terrain extends hxsl.Shader {
 				normal /= wSum;
 				normal /= wSum;
 
 
 				// Output
 				// Output
-				normal = vec4(unpackNormal(normal), 0.0);
+				var n = unpackNormal(normal);
+				transformedNormal = vec3(n.x * -1, n.y, n.z) * TBN;
 				pixelColor = vec4(albedo, 1.0);
 				pixelColor = vec4(albedo, 1.0);
-				transformedNormal = normalize(normal.xyz) * TBN;
 				roughnessValue = 1 - pbr.g * pbr.g;
 				roughnessValue = 1 - pbr.g * pbr.g;
 				metalnessValue = pbr.r;
 				metalnessValue = pbr.r;
 				occlusionValue = pbr.b;
 				occlusionValue = pbr.b;