Hello thar. I have written a voxel engine in java (using openGL) which is pretty good. There is one downside. The FPS. The engine only checks to to render blocks in your view distance and only renders blocks that you see. It doesn't even render the faces you don't see. The way the blocks are render is just by using active rendering. This keeps a steady 30FPS with a view distance of a mere 30 blocks infront of the player. I tried to speed the rendering up with Vertex buffer objects but the game uses up WAAAAAYY too much RAM (2.9G to be precise). I then made only 1 Vertex buffer object and just translated it for each cube. This put the RAM to normal levels but the FPS dropped to around 4 - 9 FPS... I then switched to display lists and made just one display list that would be translated for each cube to keep ram to a minimum. Again, 6 - 11 FPS.
Do you know of any ways to render lots of cubes at minimum ram and high FPS? I know minecraft does it relatively well and that uses OpenGl?
Voxel Rendering (OpenGL) +1 for help
How many faces (triangles) do you show?
The following is a world at 160 blocks viewing distance. With a low budget graphics card, it renders at about 30 FPS with 250000 triangles and 500 draw calls in full widescreen mode. If is based on VBOs.
You say that you use far too much memory. How much data do you have per vertex? I use the following per vertex:
[source lang="cpp"]struct VertexDataf {
glm::vec3 fNormal;
glm::vec2 fTexture;
glm::vec3 fVertex;
float fIntensity; // Pre computed The light intensity of this vertex
float fAmbient;
};
[/source]
I use back face culling to skip faces I can see.
Using only one vertex buffer object for one block means you need to change the transformation matrix for every block. This is probably very expensive, with one draw call for every block. Please explain about the data structures you used for the VBOs, and maybe we can identify why it is too much RAM.
[attachment=10777:blocks.jpeg]
The following is a world at 160 blocks viewing distance. With a low budget graphics card, it renders at about 30 FPS with 250000 triangles and 500 draw calls in full widescreen mode. If is based on VBOs.
You say that you use far too much memory. How much data do you have per vertex? I use the following per vertex:
[source lang="cpp"]struct VertexDataf {
glm::vec3 fNormal;
glm::vec2 fTexture;
glm::vec3 fVertex;
float fIntensity; // Pre computed The light intensity of this vertex
float fAmbient;
};
[/source]
I use back face culling to skip faces I can see.
Using only one vertex buffer object for one block means you need to change the transformation matrix for every block. This is probably very expensive, with one draw call for every block. Please explain about the data structures you used for the VBOs, and maybe we can identify why it is too much RAM.
[attachment=10777:blocks.jpeg]
How many faces (triangles) do you show?
The following is a world at 160 blocks viewing distance. With a low budget graphics card, it renders at about 30 FPS with 250000 triangles and 500 draw calls in full widescreen mode. If is based on VBOs.
You say that you use far too much memory. How much data do you have per vertex? I use the following per vertex:
[source lang="cpp"]struct VertexDataf {
glm::vec3 fNormal;
glm::vec2 fTexture;
glm::vec3 fVertex;
float fIntensity; // Pre computed The light intensity of this vertex
float fAmbient;
};
[/source]
I use back face culling to skip faces I can see.
Using only one vertex buffer object for one block means you need to change the transformation matrix for every block. This is probably very expensive, with one draw call for every block. Please explain about the data structures you used for the VBOs, and maybe we can identify why it is too much RAM.
[attachment=10777:blocks.jpeg]
Well I changed it so only the voxels that are active have their VBOs initialized and that brought the Ram usage down to a gig or so.
The voxels are drawn using quads and the VBO objects have 72 floats representing each vertex for each face so even though there are only 8 vertexes for a cube I have to do it for each face so it's basically 3(spacial coordiantes)*4(vertexes per face)*6(faces) = 72. Although, I'm not sure if there is a way round that or not. I'm not sure why the static VBO was taking up so much FPS.
At the moment I'm only using 1 chunk. The chunk is 128*128*128 but only a 10th of that is active due to the terrain generation being at a low level.
Is there a way to only have 8 vertexes in a VBO and draw cubes from that?
I then made only 1 Vertex buffer object and just translated it for each cube.
Are you saying that you have a draw call for each cube? If possible, batch your cubes into as few draw calls as possible. If they all use the same shader, then you would only need to batch on differing textures...but you could batch even harder than that by using a 3D texture and selecting an appropriate texture from within it based upon some parameter. You lose the ability to specify things like your model matrix in a standard uniform, but you could potentially just index in to a uniform buffer object...otherwise just repeat that data on each vertex.
At that point, you're basically replicating instanced rendering...which may be the natural next step.
At the moment I'm only using 1 chunk. The chunk is 128*128*128 but only a 10th of that is active due to the terrain generation being at a low level.
Is there a way to only have 8 vertexes in a VBO and draw cubes from that?
That would sure save a lot of memory, but I don't know how to make it efficient. Maybe using a geometry shader to generate vertices. Having one draw call for every block, with an updated model matrix every time, is not feasible.
I am using chunks of 32x32x32 blocks, but I can't say that 128 is wrong. In my case, network transfer speed is important, and too big chunks would be inefficient. When drawing at 160 blocks viewing distance, I need at most 130 chunks, at about. That makes 32x32x32x130=4 million possible cubes.
A disadvantage with too big chunks is that the chance increase that some part of it is visible, forcing you to draw all of it. The disadvantage of too small chunks is that there will be very many draw operations, which can become inefficient. Maybe 128 is a little too big? I think 32 is a good compromise, still leading to long enough lists of triangles to be efficient.
There is one way to save vertex data space. If your chunks are 128 in width, you can represent cube addresses in a byte (instead of a 32-bit float). That would reduce the memory with a factor of 4. You then need to have the shader translate the byte number to a world position coordinate (which is just what it does anyway).
[quote name='CryoGenesis' timestamp='1345400661' post='4971171']
At the moment I'm only using 1 chunk. The chunk is 128*128*128 but only a 10th of that is active due to the terrain generation being at a low level.
Is there a way to only have 8 vertexes in a VBO and draw cubes from that?
That would sure save a lot of memory, but I don't know how to make it efficient. Maybe using a geometry shader to generate vertices. Having one draw call for every block, with an updated model matrix every time, is not feasible.
I am using chunks of 32x32x32 blocks, but I can't say that 128 is wrong. In my case, network transfer speed is important, and too big chunks would be inefficient. When drawing at 160 blocks viewing distance, I need at most 130 chunks, at about. That makes 32x32x32x130=4 million possible cubes.
A disadvantage with too big chunks is that the chance increase that some part of it is visible, forcing you to draw all of it. The disadvantage of too small chunks is that there will be very many draw operations, which can become inefficient. Maybe 128 is a little too big? I think 32 is a good compromise, still leading to long enough lists of triangles to be efficient.
There is one way to save vertex data space. If your chunks are 128 in width, you can represent cube addresses in a byte (instead of a 32-bit float). That would reduce the memory with a factor of 4. You then need to have the shader translate the byte number to a world position coordinate (which is just what it does anyway).
[/quote]
Hey thanks, the reason the world size is 128 is just because of engine testing. I'm not looking to make the game multiplayer either.
I like the idea of having the blocks only hold a byte.
Each block holds 96 bits for its position so only having 24 bits would be a hell of a good Idea.
The blocks also hold 3 integers with their voxel positions in. I could just scrap those and use the byte position instead.
Although this brings down the memory usage I expect that the VBOs would bring it straight back up again. Each block holds a VBO with a ridiculous amount of floats. I tried converting it to display lists but it didn't give me any increase in fps. It decreased the fps instead.
Might have a look at the minecraft source code and see how that voxel engine draws the cubes.
Still, thanks for the idea!
Each block holds a VBO with a ridiculous amount of floats.
Actually, the VBOs can be encoded as byte integers also. I know it works, because that is the way I did it originally.
I had to go for floats eventually, because my terrain is sent through a smoothing filter (see same scene with smoothing below).
[attachment=10785:blocks1.jpeg]
[quote name='CryoGenesis' timestamp='1345408701' post='4971210']
Each block holds a VBO with a ridiculous amount of floats.
Actually, the VBOs can be encoded as byte integers also. I know it works, because that is the way I did it originally.
I had to go for floats eventually, because my terrain is sent through a smoothing filter (see same scene with smoothing below).
[attachment=10785:blocks1.jpeg]
[/quote]
I turned the positions etc to bytes. It only saved around 50k of memory in exchange for some bugs. I changed it back to floats just so the code is clean.
How did you manage to render that much with VBOs?
[quote name='larspensjo' timestamp='1345411919' post='4971231']
[quote name='CryoGenesis' timestamp='1345408701' post='4971210']
Each block holds a VBO with a ridiculous amount of floats.
Actually, the VBOs can be encoded as byte integers also. I know it works, because that is the way I did it originally.
I had to go for floats eventually, because my terrain is sent through a smoothing filter (see same scene with smoothing below).
[attachment=10785:blocks1.jpeg]
[/quote]
I turned the positions etc to bytes. It only saved around 50k of memory in exchange for some bugs. I changed it back to floats just so the code is clean.
How did you manage to render that much with VBOs?
[/quote]
Oh and also good job on that. It looks really good.
Wait, each block holds a vbo, as in you have a vbo for each cube? You should pretty much have as few vbos as you can. In your case, that could pretty much be one. As in, you input your data once - or when it changes - and only render using a single glDrawArrays (or similar) call per frame. Or divide into slightly smaller blocks of multiple cubes (which you might be doing, your description wasn't too clear about that) and call it for every N³ block of cubes, still not for every cube. You might also want to draw with index lists, though that might not be a good idea if you want to have per-face normal information. Which is not absolutely necessary, but makes lighting a bit easier.
Also, if you only have a few vbos, they don't take RAM pretty much at all, only VRAM. And assuming you use vec3 for every position, normal and texture coordinate and also use a baked float for ambient occlusion or whatever, you'll be doing 40 bytes per vertex and 960 bytes per cube. With 200MB of VRAM, that gives you over 200k cubes (a lot more in usual situations if you cull the underground faces) to play with, which ought to be more than enough.
Also, if you only have a few vbos, they don't take RAM pretty much at all, only VRAM. And assuming you use vec3 for every position, normal and texture coordinate and also use a baked float for ambient occlusion or whatever, you'll be doing 40 bytes per vertex and 960 bytes per cube. With 200MB of VRAM, that gives you over 200k cubes (a lot more in usual situations if you cull the underground faces) to play with, which ought to be more than enough.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement