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:
parent
cd6e6d7d9c
commit
8977f460ca
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
Reference in New Issue
Block a user