From 4e188840987b785d1a3c3aa71a45a1d7e35cd654 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 24 Jul 2023 22:06:33 -0700 Subject: [PATCH] feat: wip implementation for passing chunk state fo wgpu layer Signed-off-by: Michael Pollind --- .../engine/rendering/world/DummyChunk.java | 7 +-- .../mesh/resource/BufferedResource.java | 2 +- .../engine/rendering/opengl/WgpuTexture.java | 2 +- .../primitives/BlockMeshGenerator.java | 47 +++++++++++++--- .../BlockMeshGeneratorSingleShape.java | 6 +-- .../primitives/ChunkTessellator.java | 53 +++++++++++-------- .../world/block/shapes/BlockMeshPart.java | 47 +++++++++------- .../engine/world/chunks/RenderableChunk.java | 5 +- 8 files changed, 112 insertions(+), 57 deletions(-) diff --git a/engine-tests/src/test/java/org/terasology/engine/rendering/world/DummyChunk.java b/engine-tests/src/test/java/org/terasology/engine/rendering/world/DummyChunk.java index 433ed56f61e..81654a4947e 100644 --- a/engine-tests/src/test/java/org/terasology/engine/rendering/world/DummyChunk.java +++ b/engine-tests/src/test/java/org/terasology/engine/rendering/world/DummyChunk.java @@ -7,6 +7,7 @@ import org.joml.Vector3i; import org.joml.Vector3ic; import org.terasology.engine.rendering.primitives.ChunkMesh; +import org.terasology.engine.rust.resource.ChunkGeometry; import org.terasology.engine.world.block.Block; import org.terasology.engine.world.block.BlockRegionc; import org.terasology.engine.world.chunks.Chunk; @@ -19,7 +20,7 @@ public class DummyChunk implements Chunk { private final Vector3ic chunkPos; private boolean dirty; - private ChunkMesh mesh; + private ChunkGeometry mesh; private boolean ready; public DummyChunk(Vector3ic position) { @@ -147,7 +148,7 @@ public AABBfc getAABB() { } @Override - public void setMesh(ChunkMesh newMesh) { + public void setMesh(ChunkGeometry newMesh) { this.mesh = newMesh; } @@ -167,7 +168,7 @@ public boolean hasMesh() { } @Override - public ChunkMesh getMesh() { + public ChunkGeometry getMesh() { return mesh; } diff --git a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/BufferedResource.java b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/BufferedResource.java index 277a29b492a..0f7f47e5e35 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/BufferedResource.java +++ b/engine/src/main/java/org/terasology/engine/rendering/assets/mesh/resource/BufferedResource.java @@ -39,7 +39,7 @@ public int getVersion() { return this.version; } - ByteBuffer buffer() { + public ByteBuffer buffer() { return this.buffer; } diff --git a/engine/src/main/java/org/terasology/engine/rendering/opengl/WgpuTexture.java b/engine/src/main/java/org/terasology/engine/rendering/opengl/WgpuTexture.java index 0e411602032..29dea8813b1 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/opengl/WgpuTexture.java +++ b/engine/src/main/java/org/terasology/engine/rendering/opengl/WgpuTexture.java @@ -8,7 +8,7 @@ import org.terasology.engine.rendering.assets.texture.Texture; import org.terasology.engine.rendering.assets.texture.TextureData; import org.terasology.engine.rust.EngineKernel; -import org.terasology.engine.rust.TeraTexture; +import org.terasology.engine.rust.resource.TeraTexture; import org.terasology.gestalt.assets.AssetType; import org.terasology.gestalt.assets.DisposableResource; import org.terasology.gestalt.assets.ResourceUrn; diff --git a/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGenerator.java b/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGenerator.java index 12425cbee9d..16631b0802c 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGenerator.java +++ b/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGenerator.java @@ -2,6 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.engine.rendering.primitives; +import org.joml.Vector3f; +import org.joml.Vector3fc; +import org.terasology.engine.rendering.assets.mesh.resource.GLAttributes; +import org.terasology.engine.rendering.assets.mesh.resource.IndexResource; +import org.terasology.engine.rendering.assets.mesh.resource.VertexAttributeBinding; +import org.terasology.engine.rendering.assets.mesh.resource.VertexResource; +import org.terasology.engine.rendering.assets.mesh.resource.VertexResourceBuilder; +import org.terasology.engine.rust.resource.ChunkGeometry; import org.terasology.gestalt.module.sandbox.API; import org.terasology.engine.rendering.assets.mesh.Mesh; import org.terasology.engine.world.ChunkView; @@ -15,16 +23,43 @@ public interface BlockMeshGenerator { /** * Generates a block mesh at the defined location in the ChunkMesh. * - * @param view The input hunk area to acquire the Block data from. - * @param mesh The output mesh that is being generated. - * @param x Input position X. - * @param y Input position Y. - * @param z Input position Z. + * @param view The input hunk area to acquire the Block data from. + * @param mesh The output mesh that is being generated. + * @param x Input position X. + * @param y Input position Y. + * @param z Input position Z. */ - void generateChunkMesh(ChunkView view, ChunkMesh mesh, int x, int y, int z); + void generateChunkMesh(ChunkView view, ChunkMeshBufferGroup mesh, int x, int y, int z); /** * @return A standalone mesh used for items, inventory, etc... */ Mesh getStandaloneMesh(); + + + final class ChunkMeshBuffer { + public final VertexResource positionBuffer; + public int cursor = 0; + public final VertexAttributeBinding position; + public final IndexResource indices = new IndexResource(); +// public final VertexResource NormalBuffer; +// public final VertexResource uvBuffer; +// public final VertexResource ColroBuffer; +// public final VertexResource AttributeBuffer; + + public ChunkMeshBuffer() { +// { + VertexResourceBuilder builder = new VertexResourceBuilder(); + position = builder.add(0, GLAttributes.VECTOR_3_F_VERTEX_ATTRIBUTE); + positionBuffer = builder.build(); +// } + } + } + final class ChunkMeshBufferGroup { + public final ChunkMeshBuffer opaque = new ChunkMeshBuffer(); + public final ChunkMeshBuffer translucent = new ChunkMeshBuffer(); + public final ChunkMeshBuffer billboard = new ChunkMeshBuffer(); + public final ChunkMeshBuffer waterAndIce = new ChunkMeshBuffer(); + } + } diff --git a/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGeneratorSingleShape.java b/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGeneratorSingleShape.java index 55f9fdf2a64..99b904e2d71 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGeneratorSingleShape.java +++ b/engine/src/main/java/org/terasology/engine/rendering/primitives/BlockMeshGeneratorSingleShape.java @@ -34,7 +34,7 @@ public ResourceUrn getBaseUrn() { @Override - public void generateChunkMesh(ChunkView view, ChunkMesh chunkMesh, int x, int y, int z) { + public void generateChunkMesh(ChunkView view, ChunkMeshBufferGroup chunkMesh, int x, int y, int z) { final BlockAppearance blockAppearance = block.getPrimaryAppearance(); if (!blockAppearance.hasAppearance()) { // perf: Skip mesh generation for blocks without appearance, e.g., air blocks. @@ -92,7 +92,7 @@ public void generateChunkMesh(ChunkView view, ChunkMesh chunkMesh, int x, int y, .setGreen(colorSource.gf() * colorOffset.gf()) .setBlue(colorSource.bf() * colorOffset.bf()) .setAlpha(colorSource.af() * colorOffset.af()); - blockMeshPart.appendTo(chunkMesh, view, x, y, z, renderType, colorCache, sideVertexFlag); + blockMeshPart.appendTo(chunkMesh, view, x, y, z, block, colorCache, sideVertexFlag); } } } @@ -104,7 +104,7 @@ public void generateChunkMesh(ChunkView view, ChunkMesh chunkMesh, int x, int y, .setGreen(colorSource.gf() * colorOffset.gf()) .setBlue(colorSource.bf() * colorOffset.bf()) .setAlpha(colorSource.af() * colorOffset.af()); - blockAppearance.getPart(BlockPart.CENTER).appendTo(chunkMesh, view, x, y, z, renderType, colorCache, vertexFlag); + blockAppearance.getPart(BlockPart.CENTER).appendTo(chunkMesh, view, x, y, z, block, colorCache, vertexFlag); } } diff --git a/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkTessellator.java b/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkTessellator.java index a64404b8db2..26a7e1fab6e 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkTessellator.java +++ b/engine/src/main/java/org/terasology/engine/rendering/primitives/ChunkTessellator.java @@ -3,15 +3,13 @@ package org.terasology.engine.rendering.primitives; import com.google.common.base.Stopwatch; -import org.joml.Vector3f; import org.terasology.engine.monitoring.PerformanceMonitor; import org.terasology.engine.rust.EngineKernel; +import org.terasology.engine.rust.resource.ChunkGeometry; import org.terasology.engine.world.ChunkView; import org.terasology.engine.world.block.Block; import org.terasology.engine.world.chunks.Chunks; -import java.util.concurrent.TimeUnit; - /** * Generates tessellated chunk meshes from chunks. * @@ -25,45 +23,58 @@ public ChunkTessellator(EngineKernel kernel) { this.kernel = kernel; } - public ChunkMesh generateMesh(ChunkView chunkView) { + public ChunkGeometry generateMesh(ChunkView chunkView) { return generateMesh(chunkView, 1, 0); } - public ChunkMesh generateMesh(ChunkView chunkView, float scale, int border) { + public ChunkGeometry generateMesh(ChunkView chunkView, float scale, int border) { PerformanceMonitor.startActivity("GenerateMesh"); - ChunkMeshImpl mesh = new ChunkMeshImpl(); + BlockMeshGenerator.ChunkMeshBufferGroup buffer = new BlockMeshGenerator.ChunkMeshBufferGroup(); final Stopwatch watch = Stopwatch.createStarted(); // The mesh extends into the borders in the horizontal directions, but not vertically upwards, in order to cover // gaps between LOD chunks of different scales, but also avoid multiple overlapping ocean surfaces. - for (int y = 0; y < Chunks.SIZE_Y - border * 2; y++) { + for (int y = 0; y < Chunks.SIZE_Y * 2; y++) { for (int z = 0; z < Chunks.SIZE_Z; z++) { for (int x = 0; x < Chunks.SIZE_X; x++) { Block block = chunkView.getBlock(x, y, z); - block.getMeshGenerator().generateChunkMesh(chunkView, mesh, x, y, z); + block.getMeshGenerator().generateChunkMesh(chunkView, buffer, x, y, z); } } } - if (border != 0) { - float totalScale = scale * Chunks.SIZE_X / (Chunks.SIZE_X - 2 * border); - for (ChunkMesh.RenderType type : ChunkMesh.RenderType.values()) { - ChunkMesh.VertexElements elements = mesh.getVertexElements(type); - Vector3f pos = new Vector3f(); - for (int x = 0; x < elements.position.elements(); x++) { - elements.position.get(x, pos); - elements.position.set(x, pos.sub(border, 2 * border, border).mul(totalScale)); - } - } - } +// if (border != 0) { +// float totalScale = scale * Chunks.SIZE_X / (Chunks.SIZE_X - 2 * border); +// for (ChunkMesh.RenderType type : ChunkMesh.RenderType.values()) { +// ChunkMesh.VertexElements elements = mesh.getVertexElements(type); +// Vector3f pos = new Vector3f(); +// for (int x = 0; x < elements.position.elements(); x++) { +// elements.position.get(x, pos); +// elements.position.set(x, pos.sub(border, 2 * border, border).mul(totalScale)); +// } +// } +// } watch.stop(); - mesh.setTimeToGenerateBlockVertices((int) watch.elapsed(TimeUnit.MILLISECONDS)); +// mesh.setTimeToGenerateBlockVertices((int) watch.elapsed(TimeUnit.MILLISECONDS)); statVertexArrayUpdateCount++; + ChunkGeometry geometry = this.kernel.resource.createChunkGeometry(); + if (!buffer.opaque.positionBuffer.isEmpty()) { + geometry.setMeshResource(buffer.opaque.indices.buffer(), + buffer.opaque.positionBuffer.buffer(), + null, + null, + null, + null); + } +// for(BlockMeshGenerator.ChunkMeshBufferGroup.Geometry geom: buffer.geometries) { +// +// } + PerformanceMonitor.endActivity(); - return mesh; + return geometry; } public static int getVertexArrayUpdateCount() { diff --git a/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java b/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java index 1ff1bba9632..c9723f8024e 100644 --- a/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java +++ b/engine/src/main/java/org/terasology/engine/world/block/shapes/BlockMeshPart.java @@ -7,6 +7,7 @@ import org.joml.Vector3f; import org.terasology.engine.math.Direction; import org.terasology.engine.monitoring.PerformanceMonitor; +import org.terasology.engine.rendering.primitives.BlockMeshGenerator; import org.terasology.engine.rendering.primitives.ChunkMesh; import org.terasology.engine.rendering.primitives.ChunkVertexFlag; import org.terasology.engine.world.ChunkView; @@ -80,32 +81,38 @@ public BlockMeshPart mapTexCoords(Vector2f offset, float width, int frames) { return new BlockMeshPart(vertices, normals, newTexCoords, indices, frames); } - public void appendTo(ChunkMesh chunk, ChunkView chunkView, int offsetX, int offsetY, int offsetZ, - ChunkMesh.RenderType renderType, Colorc colorOffset, ChunkVertexFlag flags) { - ChunkMesh.VertexElements elements = chunk.getVertexElements(renderType); - for (Vector2f texCoord : texCoords) { - elements.uv0.put(texCoord); - } + public void appendTo(BlockMeshGenerator.ChunkMeshBufferGroup chunk, ChunkView chunkView, int offsetX, int offsetY, int offsetZ, + Block block, Colorc colorOffset, ChunkVertexFlag flags) { + + BlockMeshGenerator.ChunkMeshBuffer opaque = chunk.opaque; +// if(!block.isTranslucent()) { +// chunk.opaque; +// } + +// BlockMeshGenerator.ChunkMeshBufferGroup.Geometry geometry = chunk.geometries[renderType.ordinal()]; +// for (Vector2f texCoord : texCoords) { +// elements.uv0.put(texCoord); +// } - int nextIndex = elements.vertexCount; - elements.buffer.reserveElements(nextIndex + vertices.length); + int nextIndex = opaque.cursor; + opaque.positionBuffer.reserveElements(nextIndex + vertices.length); Vector3f pos = new Vector3f(); for (int vIdx = 0; vIdx < vertices.length; ++vIdx) { - elements.color.put(colorOffset); - elements.position.put(pos.set(vertices[vIdx]).add(offsetX, offsetY, offsetZ)); - elements.normals.put(normals[vIdx]); - elements.flags.put((byte) (flags.getValue())); - elements.frames.put((byte) (texFrames - 1)); - float[] lightingData = calcLightingValuesForVertexPos(chunkView, vertices[vIdx].add(offsetX, offsetY, offsetZ, - new Vector3f()), normals[vIdx]); - elements.sunlight.put(lightingData[0]); - elements.blockLight.put(lightingData[1]); - elements.ambientOcclusion.put(lightingData[2]); +// elements.color.put(colorOffset); + opaque.position.put(pos.set(vertices[vIdx]).add(offsetX, offsetY, offsetZ)); +// elements.normals.put(normals[vIdx]); +// elements.flags.put((byte) (flags.getValue())); +// elements.frames.put((byte) (texFrames - 1)); +// float[] lightingData = calcLightingValuesForVertexPos(chunkView, vertices[vIdx].add(offsetX, offsetY, offsetZ, +// new Vector3f()), normals[vIdx]); +// elements.sunlight.put(lightingData[0]); +// elements.blockLight.put(lightingData[1]); +// elements.ambientOcclusion.put(lightingData[2]); } - elements.vertexCount += vertices.length; + opaque.cursor += vertices.length; for (int index : indices) { - elements.indices.put(index + nextIndex); + opaque.indices.put(index + nextIndex); } } diff --git a/engine/src/main/java/org/terasology/engine/world/chunks/RenderableChunk.java b/engine/src/main/java/org/terasology/engine/world/chunks/RenderableChunk.java index 0391d6f0556..e433b608d92 100644 --- a/engine/src/main/java/org/terasology/engine/world/chunks/RenderableChunk.java +++ b/engine/src/main/java/org/terasology/engine/world/chunks/RenderableChunk.java @@ -3,6 +3,7 @@ package org.terasology.engine.world.chunks; import org.joml.Vector3f; +import org.terasology.engine.rust.resource.ChunkGeometry; import org.terasology.joml.geom.AABBfc; import org.terasology.gestalt.module.sandbox.API; import org.terasology.engine.rendering.primitives.ChunkMesh; @@ -17,7 +18,7 @@ public interface RenderableChunk { AABBfc getAABB(); - void setMesh(ChunkMesh newMesh); + void setMesh(ChunkGeometry newMesh); void setAnimated(boolean animated); @@ -25,7 +26,7 @@ public interface RenderableChunk { boolean hasMesh(); - ChunkMesh getMesh(); + ChunkGeometry getMesh(); void disposeMesh();