multimaterial optimization

This commit is contained in:
RandomityGuy 2024-06-28 13:45:27 +05:30
parent fa92b6d1af
commit ca314d734a
4 changed files with 161 additions and 97 deletions

View file

@ -1,5 +1,6 @@
package src; package src;
import h3d.scene.MultiMaterial;
import shaders.NormalMaterial; import shaders.NormalMaterial;
import shaders.NoiseTileMaterial; import shaders.NoiseTileMaterial;
import shaders.DirLight; import shaders.DirLight;
@ -672,6 +673,10 @@ class DifBuilder {
onFinish(); onFinish();
}); });
var prim = new Polygon();
var materials = [];
for (grp => tris in mats) { for (grp => tris in mats) {
var points = []; var points = [];
var normals = []; var normals = [];
@ -696,9 +701,12 @@ class DifBuilder {
uvs.push(uv2); uvs.push(uv2);
uvs.push(uv1); uvs.push(uv1);
} }
var prim = new Polygon(points);
prim.setUVs(uvs); prim.addPoints(points);
prim.setNormals(normals); prim.addUVs(uvs);
prim.addNormals(normals);
prim.nextMaterial();
var material:Material; var material:Material;
var texture:Texture; var texture:Texture;
if (canFindTex(grp)) { if (canFindTex(grp)) {
@ -740,9 +748,12 @@ class DifBuilder {
// material.mainPass.addShader(new h3d.shader.pbr.PropsValues(1, 0, 0, 1)); // material.mainPass.addShader(new h3d.shader.pbr.PropsValues(1, 0, 0, 1));
if (Debug.wireFrame) if (Debug.wireFrame)
material.mainPass.wireframe = true; material.mainPass.wireframe = true;
var mesh = new Mesh(prim, material, itr); materials.push(material);
} }
prim.endPrimitive();
var mesh = new MultiMaterial(prim, materials, itr);
shaderWorker.run(); shaderWorker.run();
}); });
for (f in loadtexs) { for (f in loadtexs) {

View file

@ -1,5 +1,6 @@
package src; package src;
import h3d.scene.MultiMaterial;
import shaders.EnvMap; import shaders.EnvMap;
import h3d.shader.CubeMap; import h3d.shader.CubeMap;
import dts.TSDrawPrimitive; import dts.TSDrawPrimitive;
@ -196,28 +197,33 @@ class DtsObject extends GameObject {
var vertexNormals = mesh.normals.map(v -> new Vector(-v.x, v.y, v.z)); var vertexNormals = mesh.normals.map(v -> new Vector(-v.x, v.y, v.z));
var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals); var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals);
var poly = new Polygon();
var usedMats = [];
for (k in 0...geometry.length) { for (k in 0...geometry.length) {
if (geometry[k].vertices.length == 0) if (geometry[k].vertices.length == 0)
continue; continue;
var poly = new Polygon(geometry[k].vertices.map(x -> x.toPoint())); poly.addPoints(geometry[k].vertices.map(x -> x.toPoint()));
poly.setNormals(geometry[k].normals.map(x -> x.toPoint())); poly.addNormals(geometry[k].normals.map(x -> x.toPoint()));
poly.setUVs(geometry[k].uvs); poly.addUVs(geometry[k].uvs);
poly.nextMaterial();
var obj = new Mesh(poly, materials[k], this.graphNodes[i]); usedMats.push(materials[k]);
} }
poly.endPrimitive();
var obj = new MultiMaterial(poly, usedMats, this.graphNodes[i]);
} else { } else {
var usedMats = []; // var usedMats = [];
for (prim in mesh.primitives) { // for (prim in mesh.primitives) {
if (!usedMats.contains(prim.matIndex)) { // if (!usedMats.contains(prim.matIndex)) {
usedMats.push(prim.matIndex); // usedMats.push(prim.matIndex);
} // }
} // }
for (k in usedMats) { // for (k in usedMats) {
var obj = new Object(this.graphNodes[i]); var obj = new Object(this.graphNodes[i]);
} // }
} }
} }
} }
@ -274,7 +280,7 @@ class DtsObject extends GameObject {
poly.normals = geometry[k].normals.map(x -> x.toPoint()); poly.normals = geometry[k].normals.map(x -> x.toPoint());
poly.uvs = geometry[k].uvs; poly.uvs = geometry[k].uvs;
var obj = new Mesh(poly, materials[k], skinObj); var obj = new MultiMaterial(poly, [materials[k]], skinObj);
} }
skinMeshData = { skinMeshData = {
meshIndex: i, meshIndex: i,

View file

@ -1,5 +1,7 @@
package src; package src;
import h3d.mat.Material;
import h3d.scene.MultiMaterial;
import shaders.EnvMap; import shaders.EnvMap;
import h3d.shader.CubeMap; import h3d.shader.CubeMap;
import shaders.NormalMaterial; import shaders.NormalMaterial;
@ -160,8 +162,8 @@ class InstanceManager {
} }
var transform = instance.emptyObj.getAbsPos(); var transform = instance.emptyObj.getAbsPos();
// minfo.meshbatch.shadersChanged = true; // minfo.meshbatch.shadersChanged = true;
minfo.meshbatch.material.mainPass.setPassName(minfo.mesh.material.mainPass.name); // minfo.meshbatch.material.mainPass.setPassName(minfo.mesh.material.mainPass.name);
minfo.meshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights; // minfo.meshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights;
minfo.meshbatch.worldPosition = transform; minfo.meshbatch.worldPosition = transform;
minfo.meshbatch.emitInstance(); minfo.meshbatch.emitInstance();
} }
@ -177,7 +179,7 @@ class InstanceManager {
// minfo.transparencymeshbatch.material.color.a = instance.gameObject.currentOpacity; // minfo.transparencymeshbatch.material.color.a = instance.gameObject.currentOpacity;
// minfo.transparencymeshbatch.material.mainPass.setPassName(minfo.mesh.material.mainPass.name); // minfo.transparencymeshbatch.material.mainPass.setPassName(minfo.mesh.material.mainPass.name);
// minfo.transparencymeshbatch.shadersChanged = true; // minfo.transparencymeshbatch.shadersChanged = true;
minfo.transparencymeshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights; // minfo.transparencymeshbatch.material.mainPass.enableLights = minfo.mesh.material.mainPass.enableLights;
// minfo.transparencymeshbatch.material.mainPass.depthWrite = false; // minfo.transparencymeshbatch.material.mainPass.depthWrite = false;
// if (dtsShader != null) { // if (dtsShader != null) {
// dtsShader.currentOpacity = instance.gameObject.currentOpacity; // dtsShader.currentOpacity = instance.gameObject.currentOpacity;
@ -214,79 +216,99 @@ class InstanceManager {
var objs = getAllChildren(object); var objs = getAllChildren(object);
var minfos = []; var minfos = [];
for (obj in objs) { for (obj in objs) {
var isMesh = obj is Mesh; var isMesh = obj is MultiMaterial;
var minfo:MeshBatchInfo = new MeshBatchInfo(); var minfo:MeshBatchInfo = new MeshBatchInfo();
minfo.instances = [new MeshInstance(obj, object)]; minfo.instances = [new MeshInstance(obj, object)];
minfo.meshbatch = isMesh ? new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material.clone(), scene) : null; minfo.meshbatch = isMesh ? new MeshBatch(cast(cast(obj, MultiMaterial).primitive), null, scene) : null;
minfo.mesh = isMesh ? cast obj : null; minfo.mesh = isMesh ? cast obj : null;
minfo.baseBounds = isMesh ? @:privateAccess cast(minfo.meshbatch.primitive, Instanced).baseBounds : null; minfo.baseBounds = isMesh ? @:privateAccess cast(minfo.meshbatch.primitive, Instanced).baseBounds : null;
if (isMesh) { if (isMesh) {
var mat = cast(obj, Mesh).material; minfo.meshbatch.materials = [];
var dtsshader = mat.mainPass.getShader(DtsTexture); for (mat in cast(obj, MultiMaterial).materials) {
if (dtsshader != null) { var matclone:Material = cast mat.clone();
minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); var dtsshader = mat.mainPass.getShader(DtsTexture);
minfo.meshbatch.material.mainPass.addShader(dtsshader); if (dtsshader != null) {
minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling; matclone.mainPass.removeShader(matclone.textureShader);
minfo.meshbatch.material.mainPass.depthWrite = mat.mainPass.depthWrite; matclone.mainPass.addShader(dtsshader);
minfo.meshbatch.material.mainPass.blendSrc = mat.mainPass.blendSrc; matclone.mainPass.culling = mat.mainPass.culling;
minfo.meshbatch.material.mainPass.blendDst = mat.mainPass.blendDst; matclone.mainPass.depthWrite = mat.mainPass.depthWrite;
minfo.meshbatch.material.mainPass.blendOp = mat.mainPass.blendOp; matclone.mainPass.blendSrc = mat.mainPass.blendSrc;
minfo.meshbatch.material.mainPass.blendAlphaSrc = mat.mainPass.blendAlphaSrc; matclone.mainPass.blendDst = mat.mainPass.blendDst;
minfo.meshbatch.material.mainPass.blendAlphaDst = mat.mainPass.blendAlphaDst; matclone.mainPass.blendOp = mat.mainPass.blendOp;
minfo.meshbatch.material.mainPass.blendAlphaOp = mat.mainPass.blendAlphaOp; matclone.mainPass.blendAlphaSrc = mat.mainPass.blendAlphaSrc;
minfo.dtsShader = dtsshader; matclone.mainPass.blendAlphaDst = mat.mainPass.blendAlphaDst;
} matclone.mainPass.blendAlphaOp = mat.mainPass.blendAlphaOp;
var phongshader = mat.mainPass.getShader(PhongMaterial); minfo.dtsShader = dtsshader;
if (phongshader != null) { }
minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); var phongshader = mat.mainPass.getShader(PhongMaterial);
minfo.meshbatch.material.mainPass.addShader(phongshader); if (phongshader != null) {
// minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling; matclone.mainPass.removeShader(matclone.textureShader);
} matclone.mainPass.addShader(phongshader);
var noiseshder = mat.mainPass.getShader(NoiseTileMaterial); // minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling;
if (noiseshder != null) { }
minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); var noiseshder = mat.mainPass.getShader(NoiseTileMaterial);
minfo.meshbatch.material.mainPass.addShader(noiseshder); if (noiseshder != null) {
// minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling; matclone.mainPass.removeShader(matclone.textureShader);
} matclone.mainPass.addShader(noiseshder);
var nmapshdr = mat.mainPass.getShader(NormalMaterial); // minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling;
if (nmapshdr != null) { }
minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); var nmapshdr = mat.mainPass.getShader(NormalMaterial);
minfo.meshbatch.material.mainPass.addShader(nmapshdr); if (nmapshdr != null) {
// minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling; matclone.mainPass.removeShader(matclone.textureShader);
} matclone.mainPass.addShader(nmapshdr);
var cubemapshdr = mat.mainPass.getShader(EnvMap); // minfo.meshbatch.material.mainPass.culling = mat.mainPass.culling;
if (cubemapshdr != null) { }
minfo.meshbatch.material.mainPass.addShader(cubemapshdr); var cubemapshdr = mat.mainPass.getShader(EnvMap);
} if (cubemapshdr != null) {
minfo.transparencymeshbatch = new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material.clone(), scene); matclone.mainPass.addShader(cubemapshdr);
minfo.transparencymeshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader); }
minfo.transparencymeshbatch.material.mainPass.addShader(dtsshader); matclone.mainPass.enableLights = mat.mainPass.enableLights;
matclone.mainPass.setPassName(mat.mainPass.name);
minfo.transparencymeshbatch.material.blendMode = Alpha; for (p in matclone.getPasses())
@:privateAccess p.batchMode = true;
minfo.meshbatch.materials.push(matclone);
minfo.transparencymeshbatch.material.mainPass.culling = mat.mainPass.culling; var matclonetransp:Material = cast mat.clone();
minfo.transparencymeshbatch.material.mainPass.depthWrite = mat.mainPass.depthWrite;
if (mat.blendMode == Alpha) { minfo.transparencymeshbatch = new MeshBatch(cast(cast(obj, MultiMaterial).primitive), null, scene);
minfo.transparencymeshbatch.material.mainPass.blendSrc = mat.mainPass.blendSrc; minfo.transparencymeshbatch.materials = [];
minfo.transparencymeshbatch.material.mainPass.blendDst = mat.mainPass.blendDst;
minfo.transparencymeshbatch.material.mainPass.blendOp = mat.mainPass.blendOp; matclonetransp.mainPass.removeShader(minfo.meshbatch.material.textureShader);
minfo.transparencymeshbatch.material.mainPass.blendAlphaSrc = mat.mainPass.blendAlphaSrc; matclonetransp.mainPass.addShader(dtsshader);
minfo.transparencymeshbatch.material.mainPass.blendAlphaDst = mat.mainPass.blendAlphaDst;
minfo.transparencymeshbatch.material.mainPass.blendAlphaOp = mat.mainPass.blendAlphaOp; matclonetransp.blendMode = Alpha;
minfo.transparencymeshbatch.material.mainPass.enableLights = mat.mainPass.enableLights;
minfo.transparencymeshbatch.material.receiveShadows = mat.receiveShadows; matclonetransp.mainPass.culling = mat.mainPass.culling;
matclonetransp.mainPass.depthWrite = mat.mainPass.depthWrite;
if (mat.blendMode == Alpha) {
matclonetransp.mainPass.blendSrc = mat.mainPass.blendSrc;
matclonetransp.mainPass.blendDst = mat.mainPass.blendDst;
matclonetransp.mainPass.blendOp = mat.mainPass.blendOp;
matclonetransp.mainPass.blendAlphaSrc = mat.mainPass.blendAlphaSrc;
matclonetransp.mainPass.blendAlphaDst = mat.mainPass.blendAlphaDst;
matclonetransp.mainPass.blendAlphaOp = mat.mainPass.blendAlphaOp;
matclonetransp.mainPass.enableLights = mat.mainPass.enableLights;
matclonetransp.receiveShadows = mat.receiveShadows;
}
matclonetransp.mainPass.enableLights = mat.mainPass.enableLights;
for (p in matclonetransp.getPasses())
@:privateAccess p.batchMode = true;
minfo.transparencymeshbatch.materials.push(matclonetransp);
// minfo.transparencymeshbatch.material.mainPass.culling = mat.mainPass.culling;
// minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.mainPass.getShader(PropsValues));
// minfo.transparencymeshbatch.material.mainPass.removeShader(minfo.transparencymeshbatch.material.mainPass.getShader(PropsValues));
// var pbrshader = mat.mainPass.getShader(PropsValues);
// if (pbrshader != null) {
// minfo.meshbatch.material.mainPass.addShader(pbrshader);
// minfo.transparencymeshbatch.material.mainPass.addShader(pbrshader);
// }
} }
// minfo.transparencymeshbatch.material.mainPass.culling = mat.mainPass.culling;
// minfo.meshbatch.material.mainPass.removeShader(minfo.meshbatch.material.mainPass.getShader(PropsValues));
// minfo.transparencymeshbatch.material.mainPass.removeShader(minfo.transparencymeshbatch.material.mainPass.getShader(PropsValues));
// var pbrshader = mat.mainPass.getShader(PropsValues);
// if (pbrshader != null) {
// minfo.meshbatch.material.mainPass.addShader(pbrshader);
// minfo.transparencymeshbatch.material.mainPass.addShader(pbrshader);
// }
} }
minfos.push(minfo); minfos.push(minfo);
} }

View file

@ -10,34 +10,40 @@ class Polygon extends MeshPrimitive {
public var tangents:Array<Float>; public var tangents:Array<Float>;
public var uvs:Array<Float>; public var uvs:Array<Float>;
public var idx:hxd.IndexBuffer; public var idx:hxd.IndexBuffer;
public var indexStarts:Array<Int>;
public var indexCounts:Array<Int>;
var currentMaterial:Int = 0;
var curTris = 0;
var bounds:h3d.col.Bounds; var bounds:h3d.col.Bounds;
var scaled = 1.; public function new(?idx) {
var translatedX = 0.; this.indexStarts = [0];
var translatedY = 0.; this.indexCounts = [];
var translatedZ = 0.; this.idx = idx;
public function new(points:Array<h3d.col.Point>, ?idx) {
this.points = []; this.points = [];
this.uvs = [];
this.normals = [];
}
public function addPoints(points:Array<h3d.col.Point>) {
for (p in points) { for (p in points) {
this.points.push(p.x); this.points.push(p.x);
this.points.push(p.y); this.points.push(p.y);
this.points.push(p.z); this.points.push(p.z);
} }
this.idx = idx; curTris += Math.floor(points.length / 3);
} }
public function setUVs(uvs:Array<h3d.prim.UV>) { public function addUVs(uvs:Array<h3d.prim.UV>) {
this.uvs = [];
for (uv in uvs) { for (uv in uvs) {
this.uvs.push(uv.u); this.uvs.push(uv.u);
this.uvs.push(uv.v); this.uvs.push(uv.v);
} }
} }
public function setNormals(normals:Array<h3d.col.Point>) { public function addNormals(normals:Array<h3d.col.Point>) {
this.normals = [];
for (n in normals) { for (n in normals) {
this.normals.push(n.x); this.normals.push(n.x);
this.normals.push(n.y); this.normals.push(n.y);
@ -45,6 +51,17 @@ class Polygon extends MeshPrimitive {
} }
} }
public function nextMaterial() {
indexStarts.push(Math.floor(this.points.length / 9));
indexCounts.push(curTris);
curTris = 0;
}
public function endPrimitive() {
indexCounts.push(curTris);
curTris = 0;
}
override function getBounds() { override function getBounds() {
if (bounds == null) { if (bounds == null) {
var b = new h3d.col.Bounds(); var b = new h3d.col.Bounds();
@ -182,6 +199,14 @@ class Polygon extends MeshPrimitive {
return Std.int(points.length / 3); return Std.int(points.length / 3);
} }
override function selectMaterial(material:Int) {
currentMaterial = material;
}
override function getMaterialIndexes(material:Int):{count:Int, start:Int} {
return {start: indexStarts[material] * 3, count: indexCounts[material] * 3};
}
override function render(engine:h3d.Engine) { override function render(engine:h3d.Engine) {
if (buffer == null || buffer.isDisposed()) if (buffer == null || buffer.isDisposed())
alloc(engine); alloc(engine);
@ -191,6 +216,6 @@ class Polygon extends MeshPrimitive {
else if (buffer.flags.has(Quads)) else if (buffer.flags.has(Quads))
engine.renderMultiBuffers(bufs, engine.mem.quadIndexes, 0, triCount()); engine.renderMultiBuffers(bufs, engine.mem.quadIndexes, 0, triCount());
else else
engine.renderMultiBuffers(bufs, engine.mem.triIndexes, 0, triCount()); engine.renderMultiBuffers(bufs, engine.mem.triIndexes, indexStarts[currentMaterial], indexCounts[currentMaterial]);
} }
} }