|
Drawing in Allegro5 (Part 2) |
pmprog
Member #11,579
January 2010
|
Sorry for the new thread, my other one seems to be locked now. I've written some code to try drawing a voxel room. Originally I tried drawing three quads per cube, one for each visible face. But when you tried to maintain a list for a 100x100x100 cube, obviously the memory usage was massive and was working with 6 million triangles, and I dropped loads of frames. So I switched to pre-rendering my cubes, and just blitting cubes on the screen, skipping cubes that were hidden by surrounding cubes, but even on a 80x80x48 scene I drop a few frames per second The obvious downside is that I'm stuck with that "view" - which isn't the worst thing in the world, but I'd have liked to have had the option to swing my camera around to each of the four isometric viewpoints. I think my main problem is most of my code is CPU based, when I really need to figure out how to make it GPU based. This site talks about Vertex Buffers There's a couple of bits with this though. Firstly, Each vertex has a colour. In order to have two cubes next to each other with different colours, I presume I'd have to have two vertices at the same location one with the colour for the cube on the left, and the other with the cube on the right? Otherwise, GL would just try and blend the colours as it renders the cube right? Secondly, I think most of frame drops are due to that most of my rendering is pushed by the CPU. So could I use vertex buffers to render bitmaps? I assume with either approach, if I was to toggle a voxel on/off, I presume I'd have to create a new vertex buffer again? Cheers
|
MikiZX
Member #17,092
June 2019
|
Vertex buffer object (VBO) would give you the best results. If 2d example can help: Creation of a VBO/IBO from a 2d map starts at line 100 of main.c In your main loop, updating part of the VBO would be done using these commands: void* lock_mem = al_lock_vertex_buffer(my_vbo_gpu_id, 0, 4, ALLEGRO_LOCK_WRITEONLY); memcpy(lock_mem, &my_vbo_data, sizeof(ALLEGRO_VERTEX) * 4); al_unlock_vertex_buffer(my_vbo_gpu_id); In your main loop you would only have one call to al_draw_indexed_buffer to draw your voxel map. |
pmprog
Member #11,579
January 2010
|
Thank you for the reply, had a quick look at your code, and I'll dig into it a bit later when I get a bit of free time. But looks like a great help, thank you. Edit: Is there a reason to create an index buffer. By looking at it, you can simply just draw the vertex buffer directly?
|
MikiZX
Member #17,092
June 2019
|
You are right about IBO. |
pmprog
Member #11,579
January 2010
|
I'm not sure this is going to work. 128x128x128 cubes = 2.1mill * 8 vertices each (I can't reuse the points, as vertex colour would differ) = ~17mill vertices. Can graphics cards even take that many vertices being uploaded? I did find a sample somewhere on this forum (can't remember where now), that rended 300,000 vertices randomly across the screen, but even that chugged my computer. Hmmm, maybe I could produce a VBO just for one layer of 128x128 cubes (131,072 vertices), then for each Z layer, modify the colours for each vertex, draw to screen, raising up the y axis. Still seems an awful lot to render. I did try caching each layer of the voxel in a bitmap, only only re-render that when a voxel is changed inside, but that consumed massive amounts of memory. Maybe to get the resolution I want, maybe I need to try this trick The only other thing I could think is decreasing the number of triangles by searching each side of each plane of the voxel model, and combining a bunch of connected colours together. But I can imagine my computation time being huge. To be fair, blitting a pre-rendered cube, and tinting it got me there without framedrops in Release mode, though I did have problems rendering that cube based on resolution. Sorry, think I'm just waffling now, and not really getting anywhere... Maybe I should ditch the voxel approach, and either go back to 2D or consider low-poly 3D
|
MikiZX
Member #17,092
June 2019
|
Possibly 'ray-marching' is something that can help you? For both 2d or 3d you could do sort of ray-trace of your voxel model and only draw the first encountered voxels (which then obscure everything behind). |
pmprog
Member #11,579
January 2010
|
I have made some decent progress https://www.youtube.com/watch?v=aFtF41gF_6Q Now this uses 6 triangles per cube, rather than 2 for drawing a prerendered cube. However, I only draw visible surfaces, and in theory, I should be able to "rotate" the camera if I get confident enough. Now, if I create a single Voxel class of 128x128x128, performance degrades quite quickly as it rebuilds the vertex buffers. However, if you create several 32x32x32 Voxels and draw them next to each other, performance is much improved. The VBOs are cached, so I'm only adjusting VBOs for rows that have been changed, and there's a "HoldRefresh" function so if I update multiple voxels in a single row, I can wait until I've done them all before the VBO is refreshed. I haven't actually measured the performance yet, but seems fairly smooth, and as long as I keep animations and transparency to a minimum, should end up being quite a smooth engine. Thanks for the suggestion, I'll keep ray-marching in mind if I do run into performance problems, but at the minute, I'm thinking it's looking fairly good.
|
|