0
\$\begingroup\$

With Metal, I need to pass in an array of primitives to the GPU to be rendered. I'm making a terrain-based voxel game like Minecraft, but I have a problem.

foring through all of the visible voxels, and in each processing the list of block IDs and Metadata into a list of primitives for rendering is asinine, because I imagine obtaining primitives from raw block data being an expensive process. Surely there's a better way.

Given that you cannot duplicate or cull vertices and planes on the fly on the GPU, doing this in the vertex shader is out of the question. My problem is when or how translate raw block data into a list of primitives ready for the GPU to apply 3D projections to it.

It would definitely be a good idea to maintain the already-processed primitive lists, and only update them when a block updates. However, maintaining these is tricky. Maintaining them one block at a time is very messy, but one voxel at a time would require stitching them together prior to rendering.

This is the foundation of a block sandbox game like Minecraft. Without it I can't progress to gameplay mechanics. My game manages voxel data with a C++ style map, of 3 dimensional arrays of 16 by 16 by 16 4-byte blocks. I simply need to know where, when, and how the process of obtaining primitives from raw block data should take place. How do most games do it?

It's also worth noting that I'm using Metal, a game framework, rather than a game engine, so if game engines generally abstract away this process and therefore this question seems nonsensical, I'm not using a game engine, I'm using a game framework.

\$\endgroup\$
5
  • \$\begingroup\$ Did you search through past questions on the voxel tag? Several of the points you raised have been answered multiple times before. \$\endgroup\$ – DMGregory Nov 10 '20 at 3:25
  • \$\begingroup\$ @DMGregory I'll try to search, but my question seems quite specific that other questions might not fully address the issue \$\endgroup\$ – user144953 Nov 10 '20 at 3:37
  • \$\begingroup\$ @DMGregory Also I recently edited my question to make each of my points more clear \$\endgroup\$ – user144953 Nov 10 '20 at 3:39
  • \$\begingroup\$ "I imagine obtaining primitives from raw block data being an expensive process" - why? \$\endgroup\$ – user253751 Nov 11 '20 at 17:00
  • \$\begingroup\$ I need to create a mesh, of primives, from just a 3d list of block IDs. First I would probably need to iterate through each one in a for loop, and for each block, create primitives based on their meshes, and then check neighboring blocks, and then neighboring voxels to cull unexposed geometry. Quite an expensive process to execute 60 times a second, before rendering, an that's just for one voxel. There would probably be dozens if not hundreds of exposed voxels at once. How can I manage this expensive process efficiently? \$\endgroup\$ – user144953 Nov 11 '20 at 18:28
0
\$\begingroup\$

I simply need to know where... and how the process of obtaining primitives from raw block data should take place. How do most games do it?

  1. Check whether any voxels have changed
  2. If so, reconstruct voxel surface geometry accordingly (this comes down to surface calculation using your boolean grid of air/voxel - a surface appears where we change from air to solid or solid to air)
  3. Submit this buffer to the GPU for rendering, each frame.

when

On each frame, whether that is on vsync or on game loop iteration. This will happen after all your game logic, such as changing of voxels, has been done, i.e. render is the last stage in the frame. So each frame consists of something like

  1. input
  2. game logic
  3. render

It's also worth noting that I'm using Metal, a game framework

Metal is not a (high level) game framework. It is a low-level, modern graphics API. There is a very great difference between those two ideas.

I get the impression you have a lot more work to do before you can be writing Metal code, comfortably, as well as developing a complex game with it. Just a suggestion that you may want to get to grips with software rendering using a simpler setup than Metal, at first.

\$\endgroup\$
6
  • \$\begingroup\$ How should I store the geometry? Should I store geometry for each voxel or create one large buffer? Creating geometry for each voxel would require a for loop in the code prior to rendering, whereas the latter would be more difficult to construct and maintain \$\endgroup\$ – user144953 Nov 11 '20 at 15:37
  • \$\begingroup\$ @user144953 One large buffer per chunk is most efficient. What your standard chunk dimensions are, only you can decide. See minecraft standard dimensions for reference? \$\endgroup\$ – Engineer Nov 11 '20 at 15:38
  • \$\begingroup\$ One large buffer per chunk, I see \$\endgroup\$ – user144953 Nov 11 '20 at 15:39
  • \$\begingroup\$ How would I handle borders? Culling unexposed geometry at voxel borders? Is the only way to do that to take neighboring voxels into account? \$\endgroup\$ – user144953 Nov 11 '20 at 15:44
  • \$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$ – Engineer Nov 11 '20 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.