You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The main changes are related to the way we access material information and textures. We will now have an array of materials information, which will be accessed by the index we calculated in the vertex shader which is now in the `outMaterialIdx` input variable (which has the `flat` modifier which states that this value should not be interpolated from vertex to fragment stage). We will be using an array of textures to access either regular textures or normal maps. The index to those textures are stored now in the `Material` struct.
668
668
669
669
670
-
Now it is the turn to examine the changes in the `SceneRender` class. We will start by defining a set of constants that will be used in the codeand by modifying the `createUniforms` according to the changes in the shaders shown before:
670
+
Now it is the turn to examine the changes in the `SceneRender` class. We will start by defining a set of constants that will be used in the code, one handle for the buffer that will have the indirect drawing instructions (`staticRenderBufferHandle`) and the number of drawing commands (`staticDrawCount`). We will need also to modify the `createUniforms` method according to the changes in the shaders shown before:
@@ -759,34 +764,153 @@ public class RenderBuffers {
759
764
}
760
765
```
761
766
762
-
You can see that we now have to bind the array of texture samplers and activate all the texture units. In addition to that, we iterate over the entities and set up the uniform values for the model matrices. After that, we call the `renderStaticMeshes` method which will be the one that populates the indirect drawingbuffer. In the next chapter we will see that we need to separate how we do this for static vs animated meshes. The `renderStaticMeshes` method is defined like this:
767
+
You can see that we now have to bind the array of texture samplers and activate all the texture units. In addition to that, we iterate over the entities and set up the uniform values for the model matrices. After that, we call the `glMultiDrawElementsIndirect` function to perform the indirect drawing. Prior to that, we need to bind the buffers that hold drawing instructions (drawing commands) and the VAO that holds the meshes and indices data. But, when do we populate the buffer for indirect drawing=? The answer is that this not need to be performed each render call, if there are no changes in the number of entities, you can record that buffer once, and use it in each render call. In this specific example, we will just populate that buffer at start-up. This means, that, if you want to make changes in the number of entities, you would nee to re-create that buffer again (you should do that for your own engine).
763
768
769
+
The method that actually builds the indirect draw buffer is called `setupStaticCommandBuffer` and starts like this:
We firs start by iterating over the models to get the position in the list of entity instances each instance is. We store that information in a `Map`` using entity identifier as key. We will need this info later on since, the indirect drawing commands will be recorded iterating over meshes associated to each model. In addition to that, we calculate the total number of meshes. After that, we will create the buffer that wil hold indirect drawing instructions and populate it:
In this case, we will populate the buffer that will hold the draw indirect instructions (by calling the `buildStaticCommandBuffer`). Each set of draw instructions si composed by five attributes, ech of the with a length of 4 bytes (total length of each set of parameters is what defines the `COMMAND_SIZE` constant). In this case, we are creating a new buffer in each draw call. This is not the most efficient way of doing it at all, but it keeps the things simple enough. In your game engine you will need to reuse a buffer. Also, there is no need to populate the indirect drawing buffer. We will keep this approach as an example, it gives you some flexibility so you can add new entities, but should think in caching for your engine.
842
+
As you can see we firs allocate a `ByteBuffer`. This buffer will hold as many instruction sets as meshes. Each set of draw instructions si composed by five attributes, ech of the with a length of 4 bytes (total length of each set of parameters is what defines the `COMMAND_SIZE` constant). We cannot allocate this buffer using `MemoryStack` since we will run out of space quickly (the stack that LWJGL uses for this is limited in size). Therefore, we need to allocate it using `MemoryUtil` and remember to manually de-allocate that once we are done. Once we have the buffer we start iterating over the meshes associated to the model. You may have a look at the beginning of this chapter to check
843
+
the struct that draw indirect requires. In addition to that, we also populate the `drawElements` uniform using the `Map` we calculated previously, to properly get the model matrix index for each entity. Finally, we just create a GPU buffer and dump the data into it.
844
+
845
+
We will need to update the `cleanup` method to free the indirect drawing buffer:
846
+
847
+
```java
848
+
publicclassRenderBuffers {
849
+
...
850
+
publicvoidcleanup() {
851
+
shaderProgram.cleanup();
852
+
glDeleteBuffers(staticRenderBufferHandle);
853
+
}
854
+
...
855
+
}
856
+
```
857
+
858
+
We will need a new method to the set up the values for the materials uniform:
idx = texturePosMap.computeIfAbsent(texture.getTexturePath(), k ->0);
891
+
uniformsMap.setUniform(name +".textureIdx", idx);
892
+
}
893
+
shaderProgram.unbind();
894
+
}
895
+
...
896
+
}
897
+
```
898
+
899
+
We just check that we are not surpassing the maximum number of supported textures (`MAX_TEXTURES`) and just create an array of materials information with the information we used in the previous chapters. The only change is that we will need to store the index of the associated texture and normal maps in the material information.
900
+
901
+
To complete the changes in the `SceneRender` class, we will create a method that wraps the `setupXX` so it can be invoked from the `Render` class:
0 commit comments