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
This commit is contained in:
OLEGSHA 2020-12-18 00:59:58 +03:00
parent cd6e6d7d9c
commit 8977f460ca
6 changed files with 128 additions and 13 deletions

View File

@ -23,7 +23,7 @@ import java.util.Objects;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
public class Face { public class Face implements Comparable<Face> {
private static final ShortBuffer GENERATE_SUCCESSIVE_LATER = null; private static final ShortBuffer GENERATE_SUCCESSIVE_LATER = null;
@ -240,4 +240,13 @@ public class Face {
this.texture = texture; 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();
}
} }

View File

@ -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;
}
}

View File

@ -19,6 +19,7 @@ package ru.windcorp.progressia.client.graphics.model;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.Arrays;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
@ -30,6 +31,8 @@ public class Shape implements Renderable {
private final ShapeRenderProgram program; private final ShapeRenderProgram program;
private final Face[] faces; private final Face[] faces;
private final Usage usage; private final Usage usage;
private FaceGroup[] groups;
private ByteBuffer vertices; private ByteBuffer vertices;
private ShortBuffer indices; private ShortBuffer indices;
@ -60,7 +63,8 @@ public class Shape implements Renderable {
private void assembleBuffers() { private void assembleBuffers() {
// TODO optimize: only update faces that requested it // TODO optimize: only update faces that requested it
sortFaces();
resizeBuffers(); resizeBuffers();
for (Face face : faces) { for (Face face : faces) {
@ -71,6 +75,8 @@ public class Shape implements Renderable {
this.vertices.flip(); this.vertices.flip();
this.indices.flip(); this.indices.flip();
assembleGroups();
needsAssembly = false; needsAssembly = false;
needsVBOUpdate = true; 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() { void markForReassembly() {
needsAssembly = true; needsAssembly = true;
@ -187,6 +238,10 @@ public class Shape implements Renderable {
return faces; return faces;
} }
public FaceGroup[] getGroups() {
return groups;
}
public Usage getUsage() { public Usage getUsage() {
return usage; return usage;
} }

View File

@ -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.attributes.*;
import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.*; import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.*;
import ru.windcorp.progressia.client.graphics.texture.Sprite; 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; import ru.windcorp.progressia.common.util.Vectors;
public class ShapeRenderProgram extends Program { public class ShapeRenderProgram extends Program {
@ -117,8 +117,8 @@ public class ShapeRenderProgram extends Program {
try { try {
enableAttributes(); enableAttributes();
for (Face face : shape.getFaces()) { for (FaceGroup group : shape.getGroups()) {
renderFace(face); renderFaceGroup(group);
} }
} finally { } finally {
disableAttributes(); disableAttributes();
@ -170,13 +170,11 @@ public class ShapeRenderProgram extends Program {
indices.bind(BindTarget.ELEMENT_ARRAY); indices.bind(BindTarget.ELEMENT_ARRAY);
} }
protected void renderFace(Face face) { protected void renderFaceGroup(FaceGroup group) {
Texture texture = face.getTexture(); TexturePrimitive texture = group.getTexture();
if (texture != null) { if (texture != null) {
Sprite sprite = texture.getSprite(); texture.bind(0);
sprite.getPrimitive().bind(0);
textureSlotUniform.set(0); textureSlotUniform.set(0);
useTextureUniform.set(1); useTextureUniform.set(1);
} else { } else {
@ -185,9 +183,9 @@ public class ShapeRenderProgram extends Program {
GL11.glDrawElements( GL11.glDrawElements(
GL11.GL_TRIANGLES, GL11.GL_TRIANGLES,
face.getIndexCount(), group.getIndexCount(),
GL11.GL_UNSIGNED_SHORT, GL11.GL_UNSIGNED_SHORT,
face.getByteOffsetOfIndices() group.getByteOffsetOfIndices()
); );
} }

View File

@ -35,7 +35,10 @@ public class TexturePrimitive implements OpenGLDeletable {
static { static {
Arrays.fill(currentlyBound, NOT_LOADED); Arrays.fill(currentlyBound, NOT_LOADED);
} }
private static int nextId = 0;
private int id = nextId++;
private int handle = NOT_LOADED; private int handle = NOT_LOADED;
private TextureData pixels; private TextureData pixels;
@ -99,4 +102,9 @@ public class TexturePrimitive implements OpenGLDeletable {
public int getHandle() { public int getHandle() {
return handle; return handle;
} }
public int getId() {
return id;
}
} }

View File

@ -55,7 +55,7 @@ public class WorldData {
} }
public void tmp_generate() { public void tmp_generate() {
final int size = 2; final int size = 6;
Vec3i cursor = new Vec3i(0, 0, 0); Vec3i cursor = new Vec3i(0, 0, 0);
for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) { for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) {