From 8977f460caf0c46040a11e8d77bce9cee817d6d0 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 18 Dec 2020 00:59:58 +0300 Subject: [PATCH] OMG THE FOOL I WAS - Faces are now grouped by texture primitive they use - Massive FPS increase - TexturePrimitive receive an additional unique ID immediately upon instantiation --- .../client/graphics/model/Face.java | 11 +++- .../client/graphics/model/FaceGroup.java | 45 +++++++++++++++ .../client/graphics/model/Shape.java | 57 ++++++++++++++++++- .../graphics/model/ShapeRenderProgram.java | 18 +++--- .../graphics/texture/TexturePrimitive.java | 8 +++ .../progressia/common/world/WorldData.java | 2 +- 6 files changed, 128 insertions(+), 13 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java index 99b1c71..15df29a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java @@ -23,7 +23,7 @@ import java.util.Objects; import ru.windcorp.progressia.client.graphics.texture.Texture; -public class Face { +public class Face implements Comparable { private static final ShortBuffer GENERATE_SUCCESSIVE_LATER = null; @@ -240,4 +240,13 @@ public class Face { this.texture = texture; } + @Override + public int compareTo(Face o) { + return Integer.compare(getSortingIndex(), o.getSortingIndex()); + } + + public int getSortingIndex() { + return texture == null ? -1 : texture.getSprite().getPrimitive().getId(); + } + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java new file mode 100644 index 0000000..f544907 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java @@ -0,0 +1,45 @@ +package ru.windcorp.progressia.client.graphics.model; + +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; + +public class FaceGroup { + + private final TexturePrimitive texture; + private final int indexCount; + private final int byteOffsetOfIndices; + + FaceGroup(Face[] faces, int start, int end) { + + Texture t = faces[start].getTexture(); + this.texture = t == null ? null : t.getSprite().getPrimitive(); + this.byteOffsetOfIndices = faces[start].getByteOffsetOfIndices(); + + int indexCount = 0; + + for (int i = start; i < end; ++i) { + Face face = faces[i]; + + assert this.texture == null + ? (face.getTexture() == null) + : (face.getTexture().getSprite().getPrimitive() == this.texture); + + indexCount += face.getIndexCount(); + } + + this.indexCount = indexCount; + } + + public TexturePrimitive getTexture() { + return this.texture; + } + + public int getIndexCount() { + return this.indexCount; + } + + public int getByteOffsetOfIndices() { + return this.byteOffsetOfIndices; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java index f53d04b..cb4fb89 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.client.graphics.model; import java.nio.ByteBuffer; import java.nio.ShortBuffer; +import java.util.Arrays; import org.lwjgl.BufferUtils; @@ -30,6 +31,8 @@ public class Shape implements Renderable { private final ShapeRenderProgram program; private final Face[] faces; private final Usage usage; + + private FaceGroup[] groups; private ByteBuffer vertices; private ShortBuffer indices; @@ -60,7 +63,8 @@ public class Shape implements Renderable { private void assembleBuffers() { // TODO optimize: only update faces that requested it - + + sortFaces(); resizeBuffers(); for (Face face : faces) { @@ -71,6 +75,8 @@ public class Shape implements Renderable { this.vertices.flip(); this.indices.flip(); + + assembleGroups(); needsAssembly = false; needsVBOUpdate = true; @@ -142,6 +148,51 @@ public class Shape implements Renderable { } } } + + private void sortFaces() { + Arrays.sort(faces); + } + + private void assembleGroups() { + int unique = countUniqueFaces(); + this.groups = new FaceGroup[unique]; + + if (faces.length == 0) return; + + int previousHandle = faces[0].getSortingIndex(); + int start = 0; + int groupIndex = 0; + + for (int i = 1; i < faces.length; ++i) { + if (previousHandle != faces[i].getSortingIndex()) { + + groups[groupIndex] = new FaceGroup(faces, start, i); + start = i; + groupIndex++; + + previousHandle = faces[i].getSortingIndex(); + } + } + + assert groupIndex == groups.length - 1; + groups[groupIndex] = new FaceGroup(faces, start, faces.length); + } + + private int countUniqueFaces() { + if (faces.length == 0) return 0; + + int result = 1; + int previousHandle = faces[0].getSortingIndex(); + + for (int i = 1; i < faces.length; ++i) { + if (previousHandle != faces[i].getSortingIndex()) { + result++; + previousHandle = faces[i].getSortingIndex(); + } + } + + return result; + } void markForReassembly() { needsAssembly = true; @@ -187,6 +238,10 @@ public class Shape implements Renderable { return faces; } + public FaceGroup[] getGroups() { + return groups; + } + public Usage getUsage() { return usage; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java index f195baa..aa24489 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java @@ -35,7 +35,7 @@ import ru.windcorp.progressia.client.graphics.backend.shaders.Program; import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.*; import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.*; import ru.windcorp.progressia.client.graphics.texture.Sprite; -import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; import ru.windcorp.progressia.common.util.Vectors; public class ShapeRenderProgram extends Program { @@ -117,8 +117,8 @@ public class ShapeRenderProgram extends Program { try { enableAttributes(); - for (Face face : shape.getFaces()) { - renderFace(face); + for (FaceGroup group : shape.getGroups()) { + renderFaceGroup(group); } } finally { disableAttributes(); @@ -170,13 +170,11 @@ public class ShapeRenderProgram extends Program { indices.bind(BindTarget.ELEMENT_ARRAY); } - protected void renderFace(Face face) { - Texture texture = face.getTexture(); + protected void renderFaceGroup(FaceGroup group) { + TexturePrimitive texture = group.getTexture(); if (texture != null) { - Sprite sprite = texture.getSprite(); - - sprite.getPrimitive().bind(0); + texture.bind(0); textureSlotUniform.set(0); useTextureUniform.set(1); } else { @@ -185,9 +183,9 @@ public class ShapeRenderProgram extends Program { GL11.glDrawElements( GL11.GL_TRIANGLES, - face.getIndexCount(), + group.getIndexCount(), GL11.GL_UNSIGNED_SHORT, - face.getByteOffsetOfIndices() + group.getByteOffsetOfIndices() ); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java index bf42fa7..71afc2d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java @@ -35,7 +35,10 @@ public class TexturePrimitive implements OpenGLDeletable { static { Arrays.fill(currentlyBound, NOT_LOADED); } + + private static int nextId = 0; + private int id = nextId++; private int handle = NOT_LOADED; private TextureData pixels; @@ -99,4 +102,9 @@ public class TexturePrimitive implements OpenGLDeletable { public int getHandle() { return handle; } + + public int getId() { + return id; + } + } diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java index 77e0a3c..4a50001 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java @@ -55,7 +55,7 @@ public class WorldData { } public void tmp_generate() { - final int size = 2; + final int size = 6; Vec3i cursor = new Vec3i(0, 0, 0); for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) {