Skip to content

Commit 91ecca6

Browse files
committed
Cache render commands
1 parent e4fe3e1 commit 91ecca6

File tree

7 files changed

+275
-227
lines changed

7 files changed

+275
-227
lines changed

chapter-20/src/main/java/org/lwjglb/engine/graph/SceneRender.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void setupData(Scene scene) {
111111
setupMaterialsUniform(scene.getTextureCache(), scene.getMaterialCache());
112112
}
113113

114-
public void setupMaterialsUniform(TextureCache textureCache, MaterialCache materialCache) {
114+
private void setupMaterialsUniform(TextureCache textureCache, MaterialCache materialCache) {
115115
List<Texture> textures = textureCache.getAll().stream().toList();
116116
int numTextures = textures.size();
117117
if (numTextures > MAX_TEXTURES) {

chapter-21/src/main/java/org/lwjglb/engine/graph/Mesh.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ public void cleanup() {
116116
glDeleteVertexArrays(vaoId);
117117
}
118118

119+
public Vector3f getAabbMax() {
120+
return aabbMax;
121+
}
122+
123+
public Vector3f getAabbMin() {
124+
return aabbMin;
125+
}
126+
119127
public int getNumVertices() {
120128
return numVertices;
121129
}

chapter-21/src/main/java/org/lwjglb/engine/graph/Render.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ public void resize(int width, int height) {
8383
public void setupData(Scene scene) {
8484
renderBuffers.loadStaticModels(scene);
8585
renderBuffers.loadAnimatedModels(scene);
86-
sceneRender.setupMaterialsUniform(scene.getTextureCache(), scene.getMaterialCache());
86+
sceneRender.setupData(scene);
87+
shadowRender.setupData(scene);
8788
List<Model> modelList = new ArrayList<>(scene.getModelMap().values());
8889
modelList.forEach(m -> m.getMeshDataList().clear());
8990
}

chapter-21/src/main/java/org/lwjglb/engine/graph/SceneRender.java

Lines changed: 129 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ public class SceneRender {
1616
private static final int COMMAND_SIZE = 5 * 4;
1717
private static final int MAX_MATERIALS = 20;
1818
private static final int MAX_TEXTURES = 16;
19+
private int animDrawCount;
20+
private int animRenderBufferHandle;
21+
private Map<String, Integer> entitiesIdxMap;
1922
private ShaderProgram shaderProgram;
23+
private int staticDrawCount;
24+
private int staticRenderBufferHandle;
2025
private UniformsMap uniformsMap;
2126

2227
public SceneRender() {
@@ -25,87 +30,13 @@ public SceneRender() {
2530
shaderModuleDataList.add(new ShaderProgram.ShaderModuleData("resources/shaders/scene.frag", GL_FRAGMENT_SHADER));
2631
shaderProgram = new ShaderProgram(shaderModuleDataList);
2732
createUniforms();
28-
}
29-
30-
private ByteBuffer buildAnimCommandBuffer(List<Model> modelList, Map<String, Integer> entitiesIdxMap) {
31-
int numMeshes = 0;
32-
for (Model model : modelList) {
33-
int numEntities = model.getEntitiesList().size();
34-
numMeshes += numEntities * model.getMeshDrawDataList().size();
35-
}
36-
37-
int firstIndex = 0;
38-
int baseInstance = 0;
39-
int drawElement = 0;
40-
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
41-
for (Model model : modelList) {
42-
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
43-
RenderBuffers.AnimMeshDrawData animMeshDrawData = meshDrawData.animMeshDrawData();
44-
Entity entity = animMeshDrawData.entity();
45-
// count
46-
commandBuffer.putInt(meshDrawData.vertices());
47-
// instanceCount
48-
commandBuffer.putInt(1);
49-
commandBuffer.putInt(firstIndex);
50-
// baseVertex
51-
commandBuffer.putInt(meshDrawData.offset());
52-
commandBuffer.putInt(baseInstance);
53-
54-
firstIndex += meshDrawData.vertices();
55-
baseInstance++;
56-
57-
String name = "drawElements[" + drawElement + "]";
58-
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
59-
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
60-
drawElement++;
61-
}
62-
}
63-
commandBuffer.flip();
64-
65-
return commandBuffer;
66-
}
67-
68-
private ByteBuffer buildStaticCommandBuffer(List<Model> modelList, Map<String, Integer> entitiesIdxMap) {
69-
int numMeshes = 0;
70-
for (Model model : modelList) {
71-
numMeshes += model.getMeshDrawDataList().size();
72-
}
73-
74-
int firstIndex = 0;
75-
int baseInstance = 0;
76-
int drawElement = 0;
77-
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
78-
for (Model model : modelList) {
79-
List<Entity> entities = model.getEntitiesList();
80-
int numEntities = entities.size();
81-
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
82-
// count
83-
commandBuffer.putInt(meshDrawData.vertices());
84-
// instanceCount
85-
commandBuffer.putInt(numEntities);
86-
commandBuffer.putInt(firstIndex);
87-
// baseVertex
88-
commandBuffer.putInt(meshDrawData.offset());
89-
commandBuffer.putInt(baseInstance);
90-
91-
firstIndex += meshDrawData.vertices();
92-
baseInstance += entities.size();
93-
94-
for (Entity entity : entities) {
95-
String name = "drawElements[" + drawElement + "]";
96-
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
97-
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
98-
drawElement++;
99-
}
100-
}
101-
}
102-
commandBuffer.flip();
103-
104-
return commandBuffer;
33+
entitiesIdxMap = new HashMap<>();
10534
}
10635

10736
public void cleanup() {
10837
shaderProgram.cleanup();
38+
glDeleteBuffers(staticRenderBufferHandle);
39+
glDeleteBuffers(animRenderBufferHandle);
10940
}
11041

11142
private void createUniforms() {
@@ -137,7 +68,7 @@ private void createUniforms() {
13768
}
13869
}
13970

140-
public void render(Scene scene, RenderBuffers globalBuffer, GBuffer gBuffer) {
71+
public void render(Scene scene, RenderBuffers renderBuffers, GBuffer gBuffer) {
14172
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBuffer.getGBufferId());
14273
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14374
glViewport(0, 0, gBuffer.getWidth(), gBuffer.getHeight());
@@ -161,59 +92,111 @@ public void render(Scene scene, RenderBuffers globalBuffer, GBuffer gBuffer) {
16192
texture.bind();
16293
}
16394

164-
Map<String, Integer> entitiesIdxMap = new HashMap<>();
16595
int entityIdx = 0;
16696
for (Model model : scene.getModelMap().values()) {
16797
List<Entity> entities = model.getEntitiesList();
16898
for (Entity entity : entities) {
169-
entitiesIdxMap.put(entity.getId(), entityIdx);
17099
uniformsMap.setUniform("modelMatrices[" + entityIdx + "]", entity.getModelMatrix());
171100
entityIdx++;
172101
}
173102
}
174103

175-
renderStaticMeshes(scene, globalBuffer, entitiesIdxMap);
176-
renderAnimMeshes(scene, globalBuffer, entitiesIdxMap);
104+
// Static meshes
105+
int drawElement = 0;
106+
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
107+
for (Model model : modelList) {
108+
List<Entity> entities = model.getEntitiesList();
109+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
110+
for (Entity entity : entities) {
111+
String name = "drawElements[" + drawElement + "]";
112+
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
113+
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
114+
drawElement++;
115+
}
116+
}
117+
}
118+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
119+
glBindVertexArray(renderBuffers.getStaticVaoId());
120+
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, staticDrawCount, 0);
177121

122+
// Animated meshes
123+
drawElement = 0;
124+
modelList = scene.getModelMap().values().stream().filter(m -> m.isAnimated()).toList();
125+
for (Model model : modelList) {
126+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
127+
RenderBuffers.AnimMeshDrawData animMeshDrawData = meshDrawData.animMeshDrawData();
128+
Entity entity = animMeshDrawData.entity();
129+
String name = "drawElements[" + drawElement + "]";
130+
uniformsMap.setUniform(name + ".modelMatrixIdx", entitiesIdxMap.get(entity.getId()));
131+
uniformsMap.setUniform(name + ".materialIdx", meshDrawData.materialIdx());
132+
drawElement++;
133+
}
134+
}
135+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, animRenderBufferHandle);
136+
glBindVertexArray(renderBuffers.getAnimVaoId());
137+
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, animDrawCount, 0);
138+
139+
glBindVertexArray(0);
178140
glEnable(GL_BLEND);
179141
shaderProgram.unbind();
180142
}
181143

182-
private void renderAnimMeshes(Scene scene, RenderBuffers globalBuffer, Map<String, Integer> entitiesIdxMap) {
183-
List<Model> modelList = scene.getModelMap().values().stream().filter(Model::isAnimated).toList();
184-
185-
ByteBuffer commandBuffer = buildAnimCommandBuffer(modelList, entitiesIdxMap);
186-
int drawCount = commandBuffer.remaining() / COMMAND_SIZE;
187-
int bufferHandle = glGenBuffers();
188-
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferHandle);
189-
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
144+
private void setupAnimCommandBuffer(Scene scene) {
145+
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> m.isAnimated()).toList();
146+
int numMeshes = 0;
147+
for (Model model : modelList) {
148+
numMeshes += model.getMeshDrawDataList().size();
149+
}
190150

191-
glBindVertexArray(globalBuffer.getAnimVaoId());
192-
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, drawCount, 0);
193-
glBindVertexArray(0);
151+
int firstIndex = 0;
152+
int baseInstance = 0;
153+
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
154+
for (Model model : modelList) {
155+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
156+
// count
157+
commandBuffer.putInt(meshDrawData.vertices());
158+
// instanceCount
159+
commandBuffer.putInt(1);
160+
commandBuffer.putInt(firstIndex);
161+
// baseVertex
162+
commandBuffer.putInt(meshDrawData.offset());
163+
commandBuffer.putInt(baseInstance);
194164

195-
MemoryUtil.memFree(commandBuffer);
196-
glDeleteBuffers(bufferHandle);
197-
}
165+
firstIndex += meshDrawData.vertices();
166+
baseInstance++;
167+
}
168+
}
169+
commandBuffer.flip();
198170

199-
private void renderStaticMeshes(Scene scene, RenderBuffers globalBuffer, Map<String, Integer> entitiesIdxMap) {
200-
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
171+
animDrawCount = commandBuffer.remaining() / COMMAND_SIZE;
201172

202-
ByteBuffer commandBuffer = buildStaticCommandBuffer(modelList, entitiesIdxMap);
203-
int drawCount = commandBuffer.remaining() / COMMAND_SIZE;
204-
int bufferHandle = glGenBuffers();
205-
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferHandle);
173+
animRenderBufferHandle = glGenBuffers();
174+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, animRenderBufferHandle);
206175
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
207176

208-
glBindVertexArray(globalBuffer.getStaticVaoId());
209-
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, drawCount, 0);
210-
glBindVertexArray(0);
211-
212177
MemoryUtil.memFree(commandBuffer);
213-
glDeleteBuffers(bufferHandle);
214178
}
215179

216-
public void setupMaterialsUniform(TextureCache textureCache, MaterialCache materialCache) {
180+
public void setupData(Scene scene) {
181+
setupEntitiesData(scene);
182+
setupStaticCommandBuffer(scene);
183+
setupAnimCommandBuffer(scene);
184+
setupMaterialsUniform(scene.getTextureCache(), scene.getMaterialCache());
185+
}
186+
187+
private void setupEntitiesData(Scene scene) {
188+
entitiesIdxMap.clear();
189+
int entityIdx = 0;
190+
for (Model model : scene.getModelMap().values()) {
191+
List<Entity> entities = model.getEntitiesList();
192+
for (Entity entity : entities) {
193+
entitiesIdxMap.put(entity.getId(), entityIdx);
194+
entityIdx++;
195+
}
196+
}
197+
}
198+
199+
private void setupMaterialsUniform(TextureCache textureCache, MaterialCache materialCache) {
217200
List<Texture> textures = textureCache.getAll().stream().toList();
218201
int numTextures = textures.size();
219202
if (numTextures > MAX_TEXTURES) {
@@ -245,4 +228,42 @@ public void setupMaterialsUniform(TextureCache textureCache, MaterialCache mater
245228
}
246229
shaderProgram.unbind();
247230
}
231+
232+
private void setupStaticCommandBuffer(Scene scene) {
233+
List<Model> modelList = scene.getModelMap().values().stream().filter(m -> !m.isAnimated()).toList();
234+
int numMeshes = 0;
235+
for (Model model : modelList) {
236+
numMeshes += model.getMeshDrawDataList().size();
237+
}
238+
239+
int firstIndex = 0;
240+
int baseInstance = 0;
241+
ByteBuffer commandBuffer = MemoryUtil.memAlloc(numMeshes * COMMAND_SIZE);
242+
for (Model model : modelList) {
243+
List<Entity> entities = model.getEntitiesList();
244+
int numEntities = entities.size();
245+
for (RenderBuffers.MeshDrawData meshDrawData : model.getMeshDrawDataList()) {
246+
// count
247+
commandBuffer.putInt(meshDrawData.vertices());
248+
// instanceCount
249+
commandBuffer.putInt(numEntities);
250+
commandBuffer.putInt(firstIndex);
251+
// baseVertex
252+
commandBuffer.putInt(meshDrawData.offset());
253+
commandBuffer.putInt(baseInstance);
254+
255+
firstIndex += meshDrawData.vertices();
256+
baseInstance += entities.size();
257+
}
258+
}
259+
commandBuffer.flip();
260+
261+
staticDrawCount = commandBuffer.remaining() / COMMAND_SIZE;
262+
263+
staticRenderBufferHandle = glGenBuffers();
264+
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, staticRenderBufferHandle);
265+
glBufferData(GL_DRAW_INDIRECT_BUFFER, commandBuffer, GL_DYNAMIC_DRAW);
266+
267+
MemoryUtil.memFree(commandBuffer);
268+
}
248269
}

0 commit comments

Comments
 (0)