diff --git a/leenkx/Sources/iron/data/Geometry.hx b/leenkx/Sources/iron/data/Geometry.hx index e111a296..6d07d38e 100644 --- a/leenkx/Sources/iron/data/Geometry.hx +++ b/leenkx/Sources/iron/data/Geometry.hx @@ -14,6 +14,7 @@ import iron.math.Vec4; import iron.math.Mat4; import iron.data.SceneFormat; import iron.data.MeshData; +import iron.data.ShaderData; class Geometry { #if lnx_deinterleaved @@ -208,7 +209,7 @@ class Geometry { for (v in 0...vertexBuffers.length) if (vertexBuffers[v].name == e.name) { vbs.push(vertexBuffers[v].buffer); - continue; + break; } if (e.name == "ipos" && instancedVB != null) { vbs.push(instancedVB); @@ -264,7 +265,7 @@ class Geometry { for (i in 0...vaLength) vertexBuffers[i] = { name: vertexArrays[i].attrib, - buffer: makeDeinterleavedVB(vertexArrays[i].values, vertexArrays[i].attrib, vertexArrays[i].size) + buffer: makeDeinterleavedVB(vertexArrays[i]) }; #else @@ -295,14 +296,20 @@ class Geometry { } #if lnx_deinterleaved - function makeDeinterleavedVB(data: ByteArray, name: String, structLength: Int): VertexBuffer { + function makeDeinterleavedVB(va: TVertexArray): VertexBuffer { var struct = new VertexStructure(); - struct.add(name, structLength == 2 ? VertexData.Short2Norm : VertexData.Short4Norm); + struct.add(va.attrib, ShaderContext.parseData(va.data)); - var vertexBuffer = new VertexBuffer(Std.int(data.byteLength / 2 / structLength), struct, usage); + var vcount = verticesCount(va); + var vertexBuffer = new VertexBuffer(vcount, struct, usage); + var stride = Std.int(struct.byteSize() / 2); var vertices = vertexBuffer.lock(); - for (i in 0...Std.int(vertices.byteLength / 2)) vertices.setInt16(i * 2, data.getInt16(i * 2)); + var di = -1; + for (i in 0...vcount) { + for (o in 0...va.size) vertices.setInt16(++di * 2, va.values[i * va.size + o]); + for (o in va.size...stride) vertices.setInt16(++di * 2, 0); + } vertexBuffer.unlock(); return vertexBuffer; diff --git a/leenkx/Sources/iron/data/MeshBatch.hx b/leenkx/Sources/iron/data/MeshBatch.hx index 1edfbcd3..1e78f29f 100644 --- a/leenkx/Sources/iron/data/MeshBatch.hx +++ b/leenkx/Sources/iron/data/MeshBatch.hx @@ -73,11 +73,11 @@ class MeshBatch { var scontext = b.shader.getContext(context); if (scontext == null) continue; g.setPipeline(scontext.pipeState); - // #if lnx_deinterleaved // TODO - // g.setVertexBuffers(b.vertexBuffers); - // #else + #if lnx_deinterleaved + g.setVertexBuffers(b.getVertexBuffers(scontext.raw.vertex_elements)); + #else g.setVertexBuffer(b.getVertexBuffer(scontext.raw.vertex_elements)); - // #end + #end g.setIndexBuffer(b.indexBuffer); Uniforms.setContextConstants(g, scontext, bindParams); @@ -127,8 +127,12 @@ class Bucket { public var batched = false; public var shader: ShaderData; +#if lnx_deinterleaved + public var vertexBuffers: Array = []; +#else var vertexBuffer: VertexBuffer; var vertexBufferMap: Map = new Map(); +#end public var indexBuffer: IndexBuffer; public var meshes: Array = []; @@ -138,8 +142,12 @@ class Bucket { public function remove() { indexBuffer.delete(); + #if lnx_deinterleaved + for (buf in vertexBuffers) buf.buffer.delete(); + #else // this.vertexBuffer is in the map, so it's also deleted here for (buf in vertexBufferMap) buf.delete(); + #end meshes = []; } @@ -151,6 +159,20 @@ class Bucket { meshes.remove(m); } +#if lnx_deinterleaved + public function getVertexBuffers(elems: Array): Array { + var vbs: Array = []; + for (e in elems) { + for (v in vertexBuffers) { + if (v.name == e.name) { + vbs.push(v.buffer); + break; + } + } + } + return vbs; + } +#else function copyAttribute(attribSize: Int, count: Int, to: ByteArray, toStride: Int, toOffset: Int, from: ByteArray, fromStride: Int, fromOffset: Int) { for (i in 0...count) { for (j in 0...attribSize) { @@ -196,6 +218,7 @@ class Bucket { } return vb; } +#end function vertexCount(g: Geometry, hasUVs: Bool): Int { var vcount = g.getVerticesLength(); @@ -240,6 +263,50 @@ class Bucket { if (mdatas.length == 0) return; +#if lnx_deinterleaved + var attrNames: Array = []; + var attrReps = new Map(); + for (md in mdatas) { + for (va in md.geom.vertexArrays) { + if (attrReps.get(va.attrib) == null) { + attrReps.set(va.attrib, va); + attrNames.push(va.attrib); + } + } + } + for (name in attrNames) { + var rep = attrReps.get(name); + var attrStruct = new VertexStructure(); + attrStruct.add(name, ShaderContext.parseData(rep.data)); + var stride = Std.int(attrStruct.byteSize() / 2); + var vtotal = 0; + for (md in mdatas) vtotal += md.geom.getVerticesCount(); + var vb = new VertexBuffer(vtotal, attrStruct, Usage.StaticUsage); + var vertices = vb.lock(); + var ai = -1; + for (md in mdatas) { + var va: TVertexArray = null; + for (v in md.geom.vertexArrays) { + if (v.attrib == name) { + va = v; + break; + } + } + if (va != null && va.values != null) { + var nverts = md.geom.getVerticesCount(); + for (i in 0...nverts) { + for (o in 0...va.size) vertices.setInt16(++ai * 2, va.values[i * va.size + o]); + for (o in va.size...stride) vertices.setInt16(++ai * 2, 0); + } + } + else { + for (i in 0...md.geom.getVerticesCount() * stride) vertices.setInt16(++ai * 2, 0); + } + } + vb.unlock(); + vertexBuffers.push({name: name, buffer: vb}); + } +#else // Pick UVs if present var vs = mdatas[0].geom.struct; for (md in mdatas) if (md.geom.struct.size() > vs.size()) vs = md.geom.struct; diff --git a/leenkx/Sources/iron/data/ShaderData.hx b/leenkx/Sources/iron/data/ShaderData.hx index 3bcbc8e4..75f55afd 100644 --- a/leenkx/Sources/iron/data/ShaderData.hx +++ b/leenkx/Sources/iron/data/ShaderData.hx @@ -102,8 +102,9 @@ class ShaderContext { constants = []; textureUnits = []; + var instStruct: VertexStructure = null; if (instancingType > 0) { // Instancing - var instStruct = new VertexStructure(); + instStruct = new VertexStructure(); instStruct.add("ipos", VertexData.Float3); if (instancingType == 2 || instancingType == 4) { instStruct.add("irot", VertexData.Float3); @@ -117,11 +118,19 @@ class ShaderContext { this.instanceStride = Std.int(instStruct.byteSize() / 4); instStruct.instanced = true; - pipeState.inputLayout = [structure, instStruct]; } - else { // Regular - pipeState.inputLayout = [structure]; + #if lnx_deinterleaved + var layouts: Array = []; + for (e in structure.elements) { + var s = new VertexStructure(); + s.add(e.name, e.data); + layouts.push(s); } + #else + var layouts = [structure]; + #end + if (instStruct != null) layouts.push(instStruct); + pipeState.inputLayout = layouts; // Depth pipeState.depthWrite = raw.depth_write;