Explorar o código

Terrain loading opti

ShiroSmith %!s(int64=5) %!d(string=hai) anos
pai
achega
5fe4643ad7
Modificáronse 3 ficheiros con 84 adicións e 42 borrados
  1. 13 13
      hide/prefab/terrain/TerrainEditor.hx
  2. 55 20
      hrt/prefab/terrain/Terrain.hx
  3. 16 9
      hrt/prefab/terrain/Tile.hx

+ 13 - 13
hide/prefab/terrain/TerrainEditor.hx

@@ -106,7 +106,7 @@ class TerrainEditor {
 		clearSavedTextures();
 		terrainPrefab.saveWeightTextures(editContext.rootContext);
 		terrainPrefab.saveHeightTextures(editContext.rootContext);
-		// terrainPrefab.saveBinary(editContext.rootContext);
+		//terrainPrefab.saveSurfaceArray(editContext.rootContext);
 		terrainPrefab.saveNormals(editContext.rootContext);
 		return;
 	}
@@ -287,12 +287,12 @@ class TerrainEditor {
 						tile.material.mainPass.stencil.setOp(Keep, Keep, Replace);
 						tile.refreshHeightMap();
 						tile.refreshIndexMap();
-						tile.refreshSurfaceWeights();
+						tile.refreshSurfaceWeightArray();
 						tile.heightMap.uploadPixels(t.prevHeightMapPixels);
 						tile.surfaceIndexMap.uploadPixels(t.prevSurfaceIndexMapPixels);
 						for( i in 0 ... t.prevWeightMapPixels.length )
 							tile.surfaceWeights[i].uploadPixels(t.prevWeightMapPixels[i]);
-						tile.generateWeightArray();
+						tile.generateWeightTextureArray();
 					}
 					else
 						terrainPrefab.terrain.removeTileAt(t.x, t.y);
@@ -394,7 +394,7 @@ class TerrainEditor {
 				strokeBuffer.prevTex = null;
 
 				copyPass.apply(strokeBuffer.tex, tile.surfaceWeights[currentBrush.index], currentBrush.brushMode.subAction ? Sub : Add);
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				clampWeight.shader.weightTextures = tile.surfaceWeightArray;
 				clampWeight.shader.weightCount = tile.surfaceWeights.length;
@@ -405,7 +405,7 @@ class TerrainEditor {
 					h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
 					clampWeight.render();
 				}
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				normalizeWeight.shader.weightTextures = tile.surfaceWeightArray;
 				normalizeWeight.shader.weightCount = tile.surfaceWeights.length;
@@ -415,7 +415,7 @@ class TerrainEditor {
 					h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
 					normalizeWeight.render();
 				}
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				var revert : TileRevertData = null;
 				for( r in paintRevertDatas )
@@ -443,7 +443,7 @@ class TerrainEditor {
 					if (tile == null ) continue;
 					for (i in 0 ... tile.surfaceWeights.length )
 						tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]);
-					tile.generateWeightArray();
+					tile.generateWeightTextureArray();
 					generateIndex.shader.weightTextures = tile.surfaceWeightArray;
 					generateIndex.shader.weightCount = tile.surfaceWeights.length;
 					h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);
@@ -484,7 +484,7 @@ class TerrainEditor {
 				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
 				copyPass.apply(strokeBuffer.prevTex, strokeBuffer.tempTex);
 				copyPass.apply(strokeBuffer.tex, strokeBuffer.tempTex, currentBrush.brushMode.subAction ? Sub : Add);
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				var engine = h3d.Engine.getCurrent();
 				clampWeight.shader.weightTextures = tile.surfaceWeightArray;
@@ -496,7 +496,7 @@ class TerrainEditor {
 					engine.pushTarget(tile.surfaceWeights[i]);
 					clampWeight.render();
 				}
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				normalizeWeight.shader.weightTextures = tile.surfaceWeightArray;
 				normalizeWeight.shader.weightCount = tile.surfaceWeights.length;
@@ -506,7 +506,7 @@ class TerrainEditor {
 					engine.pushTarget(tile.surfaceWeights[i]);
 					normalizeWeight.render();
 				}
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 
 				generateIndex.shader.weightTextures = tile.surfaceWeightArray;
 				generateIndex.shader.weightCount = tile.surfaceWeights.length;
@@ -844,7 +844,7 @@ class TerrainEditor {
 			swapIndex.render();
 			copyPass.apply(newSurfaceIndexMap, tile.surfaceIndexMap);
 			tile.surfaceWeights.remove(tile.surfaceWeights[index]);
-			tile.generateWeightArray();
+			tile.generateWeightTextureArray();
 		}
 		terrainRevertData.surfaceIndex = index;
 		terrainRevertData.surface = terrainPrefab.terrain.surfaces[index];
@@ -861,7 +861,7 @@ class TerrainEditor {
 				h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
 				normalizeWeight.render();
 			}
-			tile.generateWeightArray();
+			tile.generateWeightTextureArray();
 
 			generateIndex.shader.weightTextures = tile.surfaceWeightArray;
 			generateIndex.shader.weightCount = tile.surfaceWeights.length;
@@ -901,7 +901,7 @@ class TerrainEditor {
 				for( i in 0 ... tile.surfaceWeights.length )
 					tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]);
 
-				tile.generateWeightArray();
+				tile.generateWeightTextureArray();
 				generateIndex.shader.weightTextures = tile.surfaceWeightArray;
 				generateIndex.shader.weightCount = tile.surfaceWeights.length;
 				h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);

+ 55 - 20
hrt/prefab/terrain/Terrain.hx

@@ -123,12 +123,17 @@ class Terrain extends Object3D {
 		var prevWatch = @:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH;
 		@:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH = false;
 		var resDir = ctx.shared.loadDir(name);
-		if( resDir == null ) return;
+
+		if( resDir == null )
+			return;
+
+		// Avoid texture alloc for unpacking
+		var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution, terrain.weightMapResolution);
+
 		for( res in resDir ) {
 			var fileInfos = res.name.split(".");
 			var ext = fileInfos[1];
 			var file = fileInfos[0];
-			if( ext == "bin" ) return;
 			var coords = file.split("_");
 			var x = Std.parseInt(coords[0]);
 			var y = Std.parseInt(coords[1]);
@@ -162,30 +167,62 @@ class Terrain extends Object3D {
 				}
 				case "w":
 				if( weight ) {
-					tile.weightMapResource = res;
-					var tex = res.toTexture();
-					if( tile.surfaceWeights.length == 0 ) @:privateAccess tile.refreshSurfaceWeights();
+					if( ext == "png" ) { // Retro-compatibility
+						var weightAsPNG = res.toTexture();
+						h3d.pass.Copy.run(weightAsPNG, tmpPackedWeightTexture);
+						tile.packedWeightMapPixel = tmpPackedWeightTexture.capturePixels();
+						weightAsPNG.dispose();
+					} else {
+						var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution, terrain.weightMapResolution, res.entry.getBytes(), RGBA);
+						tmpPackedWeightTexture.uploadPixels(pixels);
+						tile.packedWeightMapPixel = pixels;
+					}
+
+					// Notice that we need the surfaceIndexMap loaded before doing the unpacking
 					var engine = h3d.Engine.getCurrent();
-					for(i in 0 ... tile.surfaceWeights.length){
+					#if editor
+					// Unpack weight from RGBA texture into a array of texture of R8, and create the TextureArray
+					if( tile.surfaceWeights.length == 0 )
+						@:privateAccess tile.refreshSurfaceWeightArray();
+					for( i in 0 ... tile.surfaceWeights.length ) {
 						engine.pushTarget(tile.surfaceWeights[i]);
 						unpackWeight.shader.indexMap = tile.surfaceIndexMap;
-						unpackWeight.shader.packedWeightTexture = tex;
+						unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture;
 						unpackWeight.shader.index = i;
 						unpackWeight.render();
 						engine.popTarget();
 					}
-					tile.generateWeightArray();
-					tex.dispose();
+					tile.generateWeightTextureArray();
+					#else
+					// Unpack weight from RGBA texture directly into the TextureArray of R8
+					tile.generateWeightTextureArray();
+					for( i in 0 ... terrain.surfaceArray.surfaceCount ) {
+						engine.pushTarget(tile.surfaceWeightArray, i);
+						unpackWeight.shader.indexMap = tile.surfaceIndexMap;
+						unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture;
+						unpackWeight.shader.index = i;
+						unpackWeight.render();
+						engine.popTarget();
+					}
+					#end
 				}
 				case"i":
 				if( index ) {
-					tile.indexMapResource = res;
-					var tex = res.toTexture();
 					if( tile.surfaceIndexMap == null ) @:privateAccess tile.refreshIndexMap();
-					h3d.pass.Copy.run(tex, tile.surfaceIndexMap);
-					tex.dispose();
+					if( ext == "png" ) { // Retro-compatibility
+						var indexAsPNG = res.toTexture();
+						h3d.pass.Copy.run(indexAsPNG, tile.surfaceIndexMap);
+						tile.indexMapPixels = tile.surfaceIndexMap.capturePixels();
+						indexAsPNG.dispose();
+					}
+					else {
+						var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution, terrain.weightMapResolution, res.entry.getBytes(), RGBA);
+						tile.indexMapPixels = pixels;
+						tile.surfaceIndexMap.uploadPixels(pixels);
+					}
 				}
 			}
+			tmpPackedWeightTexture.dispose();
 		}
 
 		#if editor
@@ -279,7 +316,7 @@ class Terrain extends Object3D {
 		for( tile in terrain.tiles ) {
 			var pixels = tile.heightMap.capturePixels();
 			var fileName = tile.tileX + "_" + tile.tileY + "_" + "h";
-			ctx.shared.savePrefabDat(fileName, "heightMap", name, pixels.bytes);
+			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
 		}
 	}
 
@@ -294,7 +331,7 @@ class Terrain extends Object3D {
 				bytes.setFloat(i*3*4+4, normals[i].y);
 				bytes.setFloat(i*3*4+8, normals[i].z);
 			}
-			ctx.shared.savePrefabDat(fileName, "normal", name, bytes);
+			ctx.shared.savePrefabDat(fileName, "bin", name, bytes);
 		}
 	}
 
@@ -308,18 +345,16 @@ class Terrain extends Object3D {
 			packWeight.render();
 
 			var pixels = packedWeightsTex.capturePixels();
-			var bytes = pixels.toPNG();
 			var fileName = tile.tileX + "_" + tile.tileY + "_" + "w";
-			ctx.shared.savePrefabDat(fileName, "png", name, bytes);
+			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
 
 			var pixels = tile.surfaceIndexMap.capturePixels();
-			var bytes = pixels.toPNG();
 			var fileName = tile.tileX + "_" + tile.tileY + "_" + "i";
-			ctx.shared.savePrefabDat(fileName, "png", name, bytes);
+			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
 		}
 	}
 
-	public function saveBinary( ctx : Context ) {
+	public function saveSurfaceArray( ctx : Context ) {
 		var count = terrain.surfaces.length;
 		for( i in 0 ... count ) {
 			var pixels = terrain.surfaceArray.albedo.capturePixels(i);

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

@@ -19,8 +19,8 @@ class Tile extends h3d.scene.Mesh {
 	public var insideFrustrum(default, null) = false;
 
 	// set by prefab loader for CPU access ingame
-	public var weightMapResource : hxd.res.Resource;
-	public var indexMapResource : hxd.res.Resource;
+	public var packedWeightMapPixel : hxd.Pixels;
+	public var indexMapPixels : hxd.Pixels;
 
 	var heightmapPixels : hxd.Pixels.PixelsFloat;
 	var shader : hrt.shader.Terrain;
@@ -194,8 +194,8 @@ class Tile extends h3d.scene.Mesh {
 			}
 		}
 	}
-
-	function refreshSurfaceWeights() {
+	
+	function refreshSurfaceWeightArray() {
 		if( terrain.surfaceArray.surfaceCount > 0 && (surfaceWeights.length != terrain.surfaceArray.surfaceCount || surfaceWeights[0].width != terrain.weightMapResolution) ) {
 				var oldArray = surfaceWeights;
 				surfaceWeights = new Array<h3d.mat.Texture>();
@@ -215,17 +215,24 @@ class Tile extends h3d.scene.Mesh {
 		}
 	}
 
+	function disposeSurfaceWeightArray() {
+		if( surfaceWeights != null ) {
+			for( t in surfaceWeights )
+				if( t != null ) t.dispose();
+		}
+	}
+
 	public function refreshTex() {
 		refreshHeightMap();
 		refreshIndexMap();
-		refreshSurfaceWeights();
-		generateWeightArray();
+		refreshSurfaceWeightArray();
+		generateWeightTextureArray();
 	}
 
-	public function generateWeightArray() {
-		if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution || surfaceWeightArray.layerCount != surfaceWeights.length ) {
+	public function generateWeightTextureArray() {
+		if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution || surfaceWeightArray.layerCount != terrain.surfaceArray.surfaceCount  ) {
 			if( surfaceWeightArray != null ) surfaceWeightArray.dispose();
-			surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution, terrain.weightMapResolution, surfaceWeights.length, [Target], R8);
+			surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution, terrain.weightMapResolution, terrain.surfaceArray.surfaceCount, [Target], R8);
 			surfaceWeightArray.setName("terrainSurfaceWeightArray");
 			surfaceWeightArray.wrap = Clamp;
 			surfaceWeightArray.preventAutoDispose();