/r/VoxelGameDev
A game development subreddit for discussing the creation of voxel games, and voxel engines.
A game development subreddit for discussing the creation of voxel games, and voxel engines.
Discussion - Question - Media
Article - Tutorial - Resource
Open Source Voxel Engines:
Information:
/r/VoxelGameDev
I had this idea for some time however idk how to make a game like it because I have not that much experience any tutorials or suggestions
did the math, his engine can render the earth 64 times at a res of 1mm per voxel. Wtf processes is he doing
I tried ursina but it's super laggy even when I optimize it
is there a language that is as simple and as capable as ursina
But is optimized to not have lag and the ability to import high triangle 3D models
please don't suggest c++ I have a bad experience with it
I've been trying to look online for this but all I could find is how to create procedural terrains like Minecraft, or smooth voxel terrains.
What I'm actually looking is a non procesual, teardown like voxel terrain, that won't me much but a simple voxelized terrain. I'm thinking maybe there's a tool out there where I could simply export a blender, or better a GAEA generated terrain and apply vixelization to it?
This is the place to show off and discuss your voxel game and tools. Shameless plugs, progress updates, screenshots, videos, art, assets, promotion, tech, findings and recommendations etc. are all welcome.
Hey, I've recently implemented my own sparse voxel octree (without basing it on any papers or anything, though I imagine it's very similar to what's out there). I don't store empty octants, or even a node that defines the area as empty, instead I'm using an 8 bit mask that determines whether each child exists or not, and then I generate empty octants from that mask if needed.
I've written a GPU ray marcher that traverses it, though it's disappointingly slow. I'm pretty sure that's down to my naive traversal, I traverse top to bottom though I keep track of the last hit node and continue on from its parent rather than starting again from the root node. But that's it.
I've heard there's a bunch of tricks to speed things up, including sorted traversal. It looks like it should be easy but I can't get my head around it for some reason.
As I understand, sorted traversal works through calculating intersections against the axis planes within octants to determine the closest nodes, enabling traversal that isn't just brute force checking against all 8 children. Does it require a direction vector, or is it purely distance based? Surely if you don't get a hit on the four closest octants you won't on the remaining four furthest either too.
Can anyone point me towards a simple code snippet of this traversal? Any language will do. I can only seem to find projects that have things broken up into tons of files and it's difficult to bounce back and forth through them all when all I want is this seemingly small optimisation.
Thanks!
I wanted to share some technical details about Lum renderer, specifically optimizations. Creating a good-looking renderer is easy (just raytrace), but making it run on less than H100 GPU is tricky sometimes. My initial goal for Lum was to make it run on integrated GPUs (with raytraced light)
I divide everything into three categories:
"Voxel" sometimes refers to a small cube conceptually, and sometimes to its data representation - material index referencing material in a material palette. Similarly, "Block" can mean a 16^(3) voxel group or a block index referencing block palette
This is more of a Voxel + GPU topic. There is some more about GPU only at the end
Common BVH tree (Bounding Volume Hierarchy) structures are fast, but not fast enough. For voxels, many tree-like implementations are redundant. I tried a lot of different approaches, but here is the catch:
Memory dependency. Aka (in C code) int a = *(b_ptr + (*shift_ptr))
. shift_ptr
has to be read before b_ptr
because you don’t know where to read yet
My thought process was:
id = 0
is empty, which is somewhat importantso there are three main data structures used in the voxel system:
3D array of int32 with size [world_size_in_blocks.xyz], storing references to blocks in the world
Array of blocks (block is [16^(3)])with size[MAX_BLOCKS], storing voxel material references in a block palette*
Array of material structures with size [MAX_MATERIALS], storing the material definitions used by voxels
*for perfomance reasons array is slightly rearranged and index differently than trivial approach
But what about models?
So now we have the general data structure built. But what’s next? Now we need to generate rays with rasterization. Why? Rasterization is faster than ray tracing first hit for voxels (number of pixels < number of visible voxels). Also, with rasterization (which effectively has totally different data structures from the voxel system), we can have non-grid-aligned voxels.
I do it like this (on my 1660 Super, all the voxels are rasterized (to gBuffer: material_id + normal) in 0.07 ms (btw i’m 69% limited by pixel fill rate). There is total ~1k non-empty blocks with 16^3 = 4096 voxels each):
Now the sweet part:
vec3 local_position
, which is position of a fragment interpolated from position of a vertex in a local block (or models, same used for them) spaceThe idea to do this appeared in my brain after reading about rendering voxels with 2D images, rasterized layer by layer, and my approach is effectively the same but 3D.
So, now we have a fast acceleration structure and a rasterized gBuffer. How does Lum raytrace shiny surfaces in under 0.3 ms? The raytracer shader processes every pixel with shiny material (how it distinguishes them is told in the end):
step_length = 0.5
, it even looks good while running ~50% fasterNon-glossy surfaces are shaded with lightmaps and a radiance field (aka per-block Minecraft lighting, but ray traced (and, in the future, directional) with almost the same traversal algorithm) and ambient occlusion.
more GPU
no matter what API you are using
vec4
s will likely limit throughput to about ~1/3). You can try to pack flat int data into a single flat int (track it in profiler)textureSize
from loop, lol) (track instruction count in profiler). Add restrict readonly
if possible. Some drivers are trash, just accept itimageLoad
)Everything said should be benchmarked in your exact usecase
Thanks for reading, feel free to leave any comments!
please star my lum project or i'll never get a job and will not be able to share voxels with you
This is the place to show off and discuss your voxel game and tools. Shameless plugs, progress updates, screenshots, videos, art, assets, promotion, tech, findings and recommendations etc. are all welcome.
I've been trying to somehow create a terrain with mesh generation much based in the system of the MMORPG Wurm Online, between each tile, there's other tiles with diferent sizes (corners and borders), any tips to bring it into reality coding for Unity?
So I am very newbee to the whole voxel generation thing, I dont intend on auto generating. Or anything correlated to LOD. I just want to spawn a fixed size grid made of white beveled cubes. And I was wondering if there is any optimization technique I should look into any tips?
I am making a Minecraft clone and I want to add infinite world generation and make it threaded. I want the threads to act like a pipeline with a generation thread then pass it to a meshing thread. If a chunk is being meshed while some of its neighbours haven't been generated yet and don't have any data to use with culling, it will just assume to cull it. The problem is when the neighbours have been generated, the mesh won't be correct and might have some culling where it isn't supposed to.
A solution to this that I can think of is to queue all neighbours for remeshing once a neighbour is generated. This does mean there will be chunks remeshing over and over which seems like it will be slow. How can I solve this?
I just released the first demo of my project, its just a basic voxel ray tracer but this will be in future the repo for my voxel engine, the 1.0 release should be out later this week/month if your interested.
https://github.com/MountainLabsYT/Quark
I haven't shared the code for the voxel ray tracer because its messy. but I'm currently trying to optimise it. Once again, full release of the basic engine later this month.
for now i'm just going to include some basic voxel raytracing code for anybody getting started with voxel raytracing.
What would be the fastest approach to create a spare octree from a grid of voxels? Are there any parallelizable algorithms so i can perform the computation on GPU with a compute shader? In my project i have to generate multiple octrees at runtime and i need something fast.
Right, so I am working on making some interesting cave generation, and I want there to be winding tunnels underground punctuated with large/small caverns. I know pretty much how Minecraft generates its worm caves, and that's by doing "abs(noise value) < some value" to create a sort of ridge noise to make noodle shapes like these:
and make the white values mean that there is air there. I have done this:
public static VoxelType DetermineVoxelType(Vector3 voxelChunkPos, float calculatedHeight, Vector3 chunkPos, bool useVerticalChunks, int randInt, int seed)
{
Vector3 voxelWorldPos = useVerticalChunks ? voxelChunkPos + chunkPos : voxelChunkPos;
// Calculate the 3D Perlin noise for caves
float caveNoiseFrequency = 0.07f; // Adjust frequency to control cave density
float wormCaveThreshold = 0.06f;
float wormCaveSizeMultiplier = 5f;
float wormCaveNoise = Mathf.Abs(Mathf.PerlinNoise((voxelWorldPos.x + seed) * caveNoiseFrequency / wormCaveSizeMultiplier, (voxelWorldPos.z + seed) * caveNoiseFrequency / wormCaveSizeMultiplier) * 2f - 1f)
+ Mathf.Abs(Mathf.PerlinNoise((voxelWorldPos.y + seed) * caveNoiseFrequency / wormCaveSizeMultiplier, (voxelWorldPos.x + seed) * caveNoiseFrequency / wormCaveSizeMultiplier) * 2f - 1f) // *2-1 to make it between -1 and 1
+ Mathf.Abs(Mathf.PerlinNoise((voxelWorldPos.z + seed) * caveNoiseFrequency / wormCaveSizeMultiplier, (voxelWorldPos.y + seed) * caveNoiseFrequency / wormCaveSizeMultiplier) * 2f - 1f);// instead of between 0 and 1
float remappedWormCaveNoise = wormCaveNoise;
remappedWormCaveNoise /=3;
if (remappedWormCaveNoise < wormCaveThreshold)
return VoxelType.Air;
// Normal terrain height-based voxel type determination
VoxelType type = voxelWorldPos.y <= calculatedHeight ? VoxelType.Stone : VoxelType.Air;
if (type != VoxelType.Air && voxelWorldPos.y < calculatedHeight && voxelWorldPos.y >= calculatedHeight - 3)
type = VoxelType.Dirt;
if (type == VoxelType.Dirt && voxelWorldPos.y <= calculatedHeight && voxelWorldPos.y > calculatedHeight - 1)
type = VoxelType.Grass;
if (voxelWorldPos.y <= -230 - randInt && type != VoxelType.Air)
type = VoxelType.Deepslate;
return type;
}
and that generates caves like this:
i know it's close to the surface but still
it's alright, but it doesn't go on for that long and it is slightly bigger than I would like. This is mostly because I'm scaling up the ridge noise by like 5 times to make the tunnels longer and less windy and decreasing the threshold so that they're not so wide. The types of caves I want that would be long constant-width windyish tunnels, and I know that that can be generated by using perlin worms, right? Those are generated by marking a starting point, taking a step in a direction according to a perlin noise map, carving out a sphere around itself, and then repeating the process until it reaches a certain length, I think. The problem I have with this is that when a chunk designates one of its voxels as a worm starting point, then carves out a perlin worm, it reaches the end of the chunk and terminates. The worms cannot go across chunks. Could this be solved by making a perlin worms noise map or something? idk. Please provide assistance if available :D