NULLSEED is a post-collapse voxel survival sandbox set generations after society fell due to misuse of advanced technology. Players live out of a camper van, build an off-grid base, and travel between small settlements to trade, take work, and gather supplies.
The most valuable loot and the most dangerous problems come from null-zones. These are localized pockets of contamination where matter and space behave inconsistently. Players enter null-zones for short, high-stakes salvage runs. They stabilize hazards, recover artifacts, and extract before conditions worsen.
The game supports solo play and co-op. It aims for fast drop-in sessions while keeping long-term persistence through base building, world changes, and relationships.
This simple page serves to document the development and progress as I go and run into interesting problems.
If you want to contribute, help with problems or ask questions, you can contact me on Discord @aze.music
Added atmospheric scatter simulation for skybox, haze and fog. This is still work in progress, the goal is to simulate atmosphere with pollutants, water droplets and dust.
This implementation uses a combination of Rayleigh/Mie scattering equations, optimized with small optical depth LUT. Rayleigh scattering approximates how different wavelengths scatter in the atmosphere, creating sky color, Mie scattering simulates light scattering in a volume of particles in a forward direction, creating haze.
There are three layers of fog:
- light scattering haze (softens distant edges)
- height based depth fog with animated wind texture (creates a sense of volume)
- distant band of fog that blends to skybox color (fades geometry to avoid hard edges)
I'll be adding SDF ray marching to add more volumetric behavior. I'm trying to avoid froxels for performance reasons.
High particle anisotropy, low Mie coefficient -> colourful sunset
Increased humidity -> higher haze (increased Mie coefficient, low particle anisotropy)
The ultimate intent is smooth blending for different day times, weather, nearby anomalies and biomes.
First attempt at indirect shadows. The Cheb occlusion and weighting is still work in progress, but first results seem good. Denser cascades are required, but everything is still running nicely at ~3.5ms on RTX3060
Also added a very fast 4-tap weighted cross blur using LDS that generates 7 mips for specular (~10us per level) + further optimizations.
Added a tiny voxel material blend on voxel edges. Materials and structures now feel more grounded and dont look like they float.
To achieve this I had to implement dynamic materials created from config so texture packing becomes automatic. The upside is I now have a texture array for each texture type. The shader needs access to all textures in order to create a blend. It scans neighbors for each edge, leveraging voxel material 3D map and LUT already present in the GPU for GI material sampling this was quite easy to achieve.
Also another big upside is I now have material properties directly in the block asset definition, right next to other gameplay properties. This also enabled me to automatically render a UI icon for that given block on load.
Perf impact is a few microseconds. Downside is one small artefact I will get rid of later..
Specular fixed, it was caused by mip blur on radiance probes not wrapping around edges, so when the octa tiles were wrapped around a sphere, the corners created a sharp seam that presented itself as a reflection artifact. Prefiltering roughness mips now taps across edges when blurring.
You can see the walls reflecting ground, sky and color correctly now, with the correct specular response. (These are traced speculars, not SSR, SSR is blended on top and only for very smooth surfaces)
I may have found the optimal path using Chebyshev dilation accelerated polycube EDT for near-SDF and low-res far-field SDF for distant geometry. JFA was fast but it tended to overestimate.
The current approach builds a truncated, neighbor-aware signed distance field per chunk by treating solid voxels as cubes (polycube field), assembling a 34^3 halo, then using Cheb (box) dilations to classify most voxels and only doing an exact Euclidean cube-distance search in the boundary band. This gives usable, sign-correct distances that preserve 1 voxel thin features, while keeping bandwidth low and allowing incremental rebuilds via small per-chunk bricks. The main optimization tricks are a bitset halo + separable dilation + distance-sorted offset list, which makes most voxels early-out to +/- and minimizes expensive searches. The con is that it is still an approximate SDF due to truncation and grid sampling (still not a full EDT), so conservative ray stepping is required and far-field coverage needs a separate coarse SDF.
Using a SM5 optimized minimal bandwidth approach and shared memory kernel, the time for a 64chunk batch is well under 2ms!! Plus with an async queue it presents itself only as minor background noise in the profiler :)
On the image, left side - real-time SDF, right side - brute-force offline calulated reference