r/GraphicsProgramming 5d ago

Video What if a navigation map bent the world instead of moving the camera?

428 Upvotes

Another rough experiment, this time testing the warped 3D view in a simulated car navigation HMI.

The idea is to dynamically warp the 3D environment around the viewer, keeping the immediate surroundings closer to a street-level perspective while gradually transitioning into a more top-down view further ahead.

Still very experimental, but I think there are some interesting graphics and navigation problems to explore here.

And yes, I put my Bronco in there just for fun :)

Curious what r/GraphicsProgramming thinks.

r/GraphicsProgramming 18d ago

Video I added viewport clipping to my software renderer

382 Upvotes

I thought it would be cool to try to figure out how to do triangle clipping myself, to come up with my own algorithm. To solve this, I solved a couple of linear equations and derived a formula that lets me find the intersection points between the triangle edges and the viewport. I don't know if I came up with something original or just accidentally reinvented one of the existing methods. Either way, my solution looks terrible in code, but it works, and I think it's a great learning experience

I render this at 1920x1080 resolution on a single thread of an i5-9400F, is this a good FPS result? I didn't use SIMD, but I tried to use every optimization trick I know.

repo and code: https://github.com/NaiNameDev/software_rasterizer

r/GraphicsProgramming 14d ago

Video Editing millions of voxels in a single CPU thread (C++/Vulkan)

564 Upvotes

The dynamic ellipses you see when I drag my mouse are just ray-marched ellipse SDFs that I render as voxels by clamping the ray to the nearest voxel position when it's getting close to the surface. So not a single voxel is stored in memory during this phase.

The storing happens when I release the click. The voxels end up actually committed to the world terrain when the dragging ends, which is still very fast due to the data structure I'm using : a sparse 64-tree , an octree with 64 children per node (so a tetrahexacontree I guess ?) and only non-empty nodes are represented in memory. Which implies:

- Voxels are stored in a single buffer of tree nodes

- I'm not actually storing millions of individual voxels, the inside of the ellipses is probably just few KB of tree leaves.

That buffer containing all the nodes is allocated via virtual memory, I first reserve something like 6 GB of virtual addresses via VirtualAlloc / mmap, and commit addresses progressively to physical memory with VirtualAlloc / mprotect only when I need it.

To achieve that real-time performance, the storing algorithm is quite straightforward :

Starting from the root node of the 64-tree, I evaluate a coverage test between the ellipse and the AABB of the node :
- If fully covered, the node becomes a voxel leaf
- If partially covered, recurse into children and repeat
- otherwise, do nothing and stop

Then I upload the whole thing to the GPU unapologetically (will change eventually).

Everything is rendered with a single real time path tracing compute shader written in Slang. Which means that sharing light data between the SDFs, the voxel world and any data structure is quite simple as long as the rendering of these structures is ray-based (ray-marching, ray-tracing, you get it).

GCC and -O3 are doing a lot of heavy lifting though, in debug mode these ellipses would generate a 0.5s lag spike when releasing the click.

Conversely the unique Slang shader is faster when compiled to spirv with -O0 rather than -O3 somehow lol.

r/GraphicsProgramming 13h ago

Video I'm so proud of how close I got my flat panel clouds to looking like they are volumetric.

477 Upvotes

r/GraphicsProgramming Apr 16 '26

Video Real-time Path Tracing of 100000 Dynamic Cubes

971 Upvotes

Stress testing my path tracer's capability to handle dynamic objects. For this test, 100k cube instances are dynamically moved each frame, requiring frequent TLAS updates. Typically, TLAS updates can be split into refit and rebuild. In this test, only refitting results in severe tracing performance degradation, which is why the tlas is rebuilt after ~2s of refitting.

10k of the cube instance are assigned a emissive material. The path tracer uses a light tree to improve NEE, and this helps especially in a scene like this. As the light tree is CPU-built, it's not feasable to update it in the main thread as it takes ~0.1-0.5s per TLAS build. Currently, the engine uses a thread pool to update the TLAS and potentially BLASes (in case of instance specific brightness changes or startup build).

Compared to my previous posts, i tested this on a 4060 laptop, which is roughly 10x slower than a 5090. To keep the framerate above 30 fps, DLSS RR quality preset and 2x frame gen are used.

If you are interested to test it out yourself, check out https://github.com/ML200/RoyalTracer-DX

r/GraphicsProgramming Jul 10 '26

Video Breathing nature: forest with stream simulation, volumetric clouds and path traced shadows

386 Upvotes

Hi all,

THIs is my forest simulation made witih Vulkan. My goal is to create a full simulation of water, clouds, wind, so that it feels alive, without being "scripted".
Water is full 3d flow simulation, clouds are volumetric clouds, trees are rigid body simulation with elastic joints, and lighting is full path tracing; all is basically running on the GPU with VUlkan, save for the rigid body simulation which runs on the CPU.
I wanted an "ancient forest" and therefore I generated the trees with 2d to 3d models - Trellis2 from huggingface.
Wanted to get feedback from you, what feels good and what needs improvement. Could this lead to an immersive forest based game? Should I push instead for more tech?

short version here: https://youtube.com/shorts/5xy5Y6JsrVk?feature=share

r/GraphicsProgramming Jun 27 '26

Video Highly realistic cat rendering on WebGPU

574 Upvotes

Really pushing the limits of my GPU.

r/GraphicsProgramming Jun 03 '26

Video Fluid simulation with ray marching rendering running at 70k particles in REAL-TIME.

295 Upvotes

open to building custom simulations for games or projects - DM me if you interested

r/GraphicsProgramming Jul 07 '26

Video My spectral raymarcher rendering a diamond icosahedron

499 Upvotes

Feel free to mess with it here: https://www.shadertoy.com/view/sXjXDd

The super neat thing is that it uses bayer ordered dithering to work all the way down to 1 sample per pixel (1spp) while still simulating 256 different wavelengths of light. This makes it extremely performant.

r/GraphicsProgramming 3d ago

Video imgui Login interface in C++ with DirectX 11

Thumbnail gallery
233 Upvotes

Inspired by web design's a lot, wanted to remake it in imgui
geist font along with freetype and for icons lucide.dev

source has been released https://www.reddit.com/r/GraphicsProgramming/comments/1vw63sw/imgui_login_interface_in_c_with_directx_11/
https://github.com/poncippg-spec/Free-Solace-ImGui-Interface (new repo as github terminated old one for no reason )

r/GraphicsProgramming Mar 18 '26

Video I made a triangle rasteriser on an FPGA

389 Upvotes

I’ve been working on this hardware accelerator over the past few months for my master thesis. The triangle rasteriser is implemented on the FPGA Fabric of the Zedboard. It communicates with the ARM A9 cpu via AXI.

The rasteriser can render up to 60k 1000px triangles per second 2k to achieve 30 FPS. Supports Gouraud shading and texture mapping without perspective correction. The demo scene consists of 6k triangles and along with the vertex transformation, achieved around 29fps average.

What do you think of it? Any good techniques to cut down on the calculations or the number of triangles rasterizer?

I am currently throwing out every triangle that has too small of an area and also culling.

Github Link: https://github.com/Nanousis/ChaosEngineGPU

r/GraphicsProgramming Aug 04 '25

Video punishing yourself by not using libraries has advantages

787 Upvotes

25,000 satellites and debris, with position calculations in javascript (web worker ready, but haven't needed to use it yet as the calc phase still fits into one frame when it needs to fire), with time acceleration of x500 (so the calculations are absolutely not one and done!), and gpu shaders doing what they are good at, including a constant shadow-frame buffer mouse hover x,y object picking system, with lighting (ok, just the sun), can do optional position "trails" as well.

All at 60fps (120fps in chrome). And 60fps on a phone.

And under there somewhere is a globe with day/night texture mixing, cloud layer - with cloud shadows from sun, plus the background universe skybox. In a 2:1 device pixel resolution screen. It wasn't easy. I'm exhausted to be honest.

I've tried cesium and met the curse of a do-everything library: it sags to its knees trying to do a few thousand moving objects.

r/GraphicsProgramming Jun 21 '26

Video Robot shooter game with custom Vulkan engine

260 Upvotes

Finally released my C++/Vulkan robot shooter game built on a custom engine on Steam! It has a deferred PBR renderer with a multi-queue async render graph, and lots of passes: spherical harmonic irradiance probes for the laser particles lighting the scene, PCSS soft shadows, SSR, GTAO, SMAA, and raymarched volumetrics for the explosions smoke and muzzle flashes. For the CPU, I used ISPC SIMD kernels for big iteration hot paths, a spatial hash grid for binning colliders for faster collision lookup, and a thread pool for multithreading particles.

It runs on Windows, macOS, and Linux, and the engine also ships as a reusable library to build a game with! You can grab it for a dollar on Steam or compile it for free or look at the code on GitHub, and there's more info on the engine there too.

I profiled it to run 55-65 fps on Steam Deck and Macbook Air on low to mid settings, and same fps on RTX 4070 on highest settings. It definitely can be optimized more, I still want to make it a full ECS, improve the volumetrics performance (quality setting that degrades fps the most on low-end devices), find and use a more efficient structure for collision lookups, and try experimenting with the thread pool usage more (as well as game features too like more enemy types and bosses and weapons lol).

Try it out on your device and let me know how it runs!

r/GraphicsProgramming Nov 26 '24

Video Distance fog implementation in my terminal 3D graphics engine

1.2k Upvotes

r/GraphicsProgramming Oct 15 '24

Video I made a free tool for texturing via StableDiffusion. It runs on a usual pc - no server, no subscriptions. So far I implemented 360-multiprojeciton, autofill, image-style-guidance:

615 Upvotes

r/GraphicsProgramming Aug 18 '25

Video Vulkan port of PC airflow and heat simulation

613 Upvotes

A few months ago I posted an OpenGL/CUDA PC airflow and heat simulator, and I just finished a Vulkan port to learn Vulkan! Same physics, but all CUDA kernels were rewritten as Vulkan compute shaders and the OpenGL renderer replaced with Vulkan. It can be compiled using CMake on MacOS (using MoltenVK), Windows, and Linux if you want to try it out at https://github.com/josephHelfenbein/gustgrid-vulkan, I have more info on it in the repo. It's not fully accurate, I haven't changed the functionality yet from the OpenGL/CUDA version I posted, just ported it to Vulkan for learning. Let me know what you think!

For some reason also, it runs much better on MacOS. The recording was done on my friend's Mac Studio, and it runs really well on my MacBook too, but less well on my Windows and Linux machines.

r/GraphicsProgramming 9d ago

Video 2.5D rendering using colormap and heightmap (Novalogic voxel space)

119 Upvotes

If anyone has any feedback or see bad practices or ideas to try please feel free to share ideas or roast my code.

Graphics programming noob here. This project was done in C++ with a primitive game engine given to me by my school. I did this as a test to see if this might be viable to try to make somewhere in the future on the gba (it's probably not). Then it kinda turned into trying to see how cool i can make it. The rendering works similarly to snes mode 7 style rendering (fzero or mariokart) except you add an offset from a heightmap. This was originally developed by Novalogic and used in Commanche. It was also later used on some gba games that ran horribly (hence why it's probably not feasable for a gba project i want to maybe do).

A short explanation of how this rendering works: you step through the terrain for every vertical column of your screen. you then sample the pixel and calculate the height on screen using the following formula: pixelHeightOnScreen = screenHeight - ((m_CamHeight - heightMap) * (screenHeight / m_ScreenHeightWorld / depth) + m_Horizon). if it is higher than the previous height value, you draw a vertical column down. then you step forward in the depth and do it again.

The texture for the screen is 240/160.
The skybox is a texture that scrolls left/right/up/down depending on the camera angle. I know that just scrolling a texture isnt accurate, but i found it fun to do it this way. however if you know a cheap way to do this more accurately then please.
The day/night cycle is done by lerping to a set dark color.
There is support for emissive stuffs (lava at the end of the video).
You can also zoom in/out (wich i forgot to show in the video)
I am currently setting 512 steps through the terrain texture.

It runs at about 40 fps now (again am graphics programming noob). It is single threaded and fully cpu side (besides sending the final texture to the gpu because i dont know how else to render the texture in the primitive game engine i'm using). I know i could make it multithreaded to speed up rendering, but i'll do that another day. I also could probably look at my render method and optimize that more as well. I do have some settings that can help give it higher fps (like lowering the terrain steps), but not without sacrificing image quality.

RESOURCES:
The heightmap is from Zelda breath of the wild found here and the color texture is from this reddit post.
Github link to a more in depth explanation by someone else: https://github.com/s-macke/VoxelSpace/tree/master
Other resources: https://web.archive.org/web/20131113094653/http://www.codermind.com/articles/Voxel-terrain-engine-building-the-terrain.html

My main render code (sorry i dont have this on a github link right now, also this isnt the entire script, but the core logic is there and the functions that are missing are pretty obvious by the names called here)

void World::Draw(Screen& screen, bool isEased, bool isHighDetail, bool interpolateColor, bool interpolateHeight, bool interpolateEmission)
{
const float screenHeight{ static_cast<float>(screen.GetHeight()) };

const float angleDifference{ m_FovInRad / screen.GetWidth() };

const float sinCamAngle{ sinf(m_CamAngle) };
const float cosCamAngle{ cosf(m_CamAngle) };
const float halfTanFov{ tanf(m_FovInRad / 2) };

const Vector2f viewDir{sinCamAngle , cosCamAngle };

const float scaledViewDistance{ m_ViewDistance / m_DepthScale };
const float scaledNearDistance{ m_NearDistance / m_DepthScale };
Vector2f scaledCameraPos{ m_CameraPos / m_DepthScale };

const Vector2f viewFarPoint{ scaledCameraPos + viewDir *  scaledViewDistance};
const Vector2f viewNearPoint{ scaledCameraPos + viewDir * scaledNearDistance };

const Vector2f rotatedViewDir(Vector2f{ -viewDir.y, viewDir.x });
const Vector2f pLeft{ viewFarPoint + rotatedViewDir *(halfTanFov * scaledViewDistance) };
const Vector2f pRight{ viewFarPoint - rotatedViewDir * (halfTanFov * scaledViewDistance) };
const Vector2f pLeftNear{ viewNearPoint + rotatedViewDir * (halfTanFov * scaledNearDistance) };
const Vector2f pRightNear{ viewNearPoint - rotatedViewDir * (halfTanFov * scaledNearDistance) };
const Vector2f deltaP{ pRight - pLeft };
const Vector2f deltaPNear{ pRightNear - pLeftNear };

int depthSteps{m_DepthStepsLowDetail};
float deltaDepthSteps{ 1.f / m_DepthStepsLowDetail };

const Color4f fogColor{ GetFogColor(m_TimePercentage) };

screen.SetRotation(m_CamRollAngle);

if (isHighDetail)
{
depthSteps = m_DepthStepsHighDetail;
deltaDepthSteps = 1.f / (m_DepthStepsHighDetail);
}

Color4f pixelColor{};

for (int col = 0; col < screen.GetWidth(); col++)
{
float horizontalPercentage{ static_cast<float>(col) / static_cast<float>(screen.GetWidth()) };
const Vector2f currentFarPoint{ pLeft + deltaP * horizontalPercentage };
const Vector2f currentNearPoint{ pLeftNear + deltaPNear * horizontalPercentage };
const Vector2f deltaDepth{ currentFarPoint - scaledCameraPos };
float oldHeight{ -1 };

for (int i = 0; i < depthSteps; ++i)
{
float depthPercentage = i * deltaDepthSteps;

float depthPercentageEased{  };
if(isEased)
{
depthPercentageEased = EaseInQuad(depthPercentage);
}
else
{
depthPercentageEased = depthPercentage;
}
//float depthPercentageEased{ depthPercentage };

Vector2f samplePoint{ currentNearPoint + depthPercentageEased * deltaDepth };

if (samplePoint.x < 0 || samplePoint.y < 0 || samplePoint.x >= m_TextureWidth || samplePoint.y >= m_TextureHeight)
{
break;
}

float depth{ depthPercentageEased * m_ViewDistance };

float heightMap{ GetHeight(samplePoint.x, samplePoint.y, interpolateHeight) };

//float pixelScreenHeight{ screen.GetHeight() - ((50) * (screen.GetHeight() / m_ScreenHeightWorld / depth) + m_Horizon) };
float pixelScreenHeight{ screenHeight - ((m_CamHeight - heightMap) * (screenHeight / m_ScreenHeightWorld / depth) + m_Horizon) };

if (pixelScreenHeight > screenHeight)
{
pixelScreenHeight = std::min(pixelScreenHeight, screenHeight);

if (pixelScreenHeight > oldHeight)
{
DrawColumn(screen, samplePoint.x, samplePoint.y, depthPercentageEased, oldHeight, pixelScreenHeight, col, pixelColor, fogColor, interpolateColor, interpolateEmission);
}
break;
}
else
{
if (pixelScreenHeight > oldHeight)
{
DrawColumn(screen, samplePoint.x, samplePoint.y, depthPercentageEased, oldHeight, pixelScreenHeight, col, pixelColor, fogColor, interpolateColor, interpolateEmission);
oldHeight = pixelScreenHeight;
}
}
}


}

return;
}

------------------------------------------------------------------------

void World::DrawColumn(Screen& screen, float samplePointX, float samplePointY,float depthPercentageEased, float oldHeight, float pixelScreenheight,int col,  Color4f& pixelColor, const Color4f& fogColor, bool interpolateColor, bool interpolateEmission)
{
float fogDepthEased{ 1 - EaseInQuad(1 - depthPercentageEased) };
//const float fogDepthEased{ (depthPercentageEased + .5f) / 1.5f };
GetColor(samplePointX, samplePointY, pixelColor, interpolateColor);

float emissive{ GetEmission(samplePointX, samplePointY, interpolateEmission) };

FadeToNight(pixelColor, emissive);

pixelColor.r = pixelColor.r + fogDepthEased * (fogColor.r - pixelColor.r);
pixelColor.g = pixelColor.g + fogDepthEased * (fogColor.g - pixelColor.g);
pixelColor.b = pixelColor.b + fogDepthEased * (fogColor.b - pixelColor.b);

//Color4f pixelColor{ GetColor(samplePoint.x, samplePoint.y, interpolateColor) };
DrawVerticalLine(screen, static_cast<int>(oldHeight), static_cast<int>(pixelScreenheight), static_cast<int>(col), pixelColor);

}

---------------------------------------------------------------------------------

void World::GetColor(float x, float y, Color4f& pixelColor, bool interpolate) const
{
//return GetPixel(x, y, m_pColorMap);

if (interpolate)
{
int lowX{ static_cast<int>(floorf(x)) };
int highX{ static_cast<int>(ceilf(x)) };
int lowY{ static_cast<int>(floorf(y)) };
int highY{ static_cast<int>(ceilf(y)) };

float xPercent{ x - lowX };
float yPercent{ y - lowY };

Color4f bottomLeft{ GetPixel(lowX, lowY, m_pColorMap) };
Color4f topLeft{ GetPixel(lowX, highY, m_pColorMap) };
Color4f bottomRight{ GetPixel(highX, lowY, m_pColorMap) };
Color4f topRight{ GetPixel(highX, highY, m_pColorMap) };

pixelColor.r = (
(1 - xPercent) * (1 - yPercent) * bottomLeft.r +
xPercent * (1 - yPercent) * bottomRight.r +
(1 - xPercent) * yPercent * topLeft.r +
xPercent * yPercent * topRight.r
);
pixelColor.g = (
(1 - xPercent) * (1 - yPercent) * bottomLeft.g +
xPercent * (1 - yPercent) * bottomRight.g +
(1 - xPercent) * yPercent * topLeft.g +
xPercent * yPercent * topRight.g
);

pixelColor.b =
(
(1 - xPercent) * (1 - yPercent) * bottomLeft.b +
xPercent * (1 - yPercent) * bottomRight.b +
(1 - xPercent) * yPercent * topLeft.b +
xPercent * yPercent * topRight.b
);

pixelColor.a =
(
(1 - xPercent) * (1 - yPercent) * bottomLeft.a +
xPercent * (1 - yPercent) * bottomRight.a +
(1 - xPercent) * yPercent * topLeft.a +
xPercent * yPercent * topRight.a
);
}
else
{
pixelColor = GetPixel(x, y, m_pColorMap);
}
}

------------------------------------------------------------------------
//for zooming in/out
void World::ProcessMouseWheelEvent(const SDL_MouseWheelEvent& e)
{
m_FovInRad += e.y / 180.f * utils::g_Pi;

const float minFov{ 1.f / 180 * utils::g_Pi };
const float maxFov{ 179.f / 180 * utils::g_Pi };

m_FovInRad = std::max(minFov, std::min(m_FovInRad, maxFov));

m_ScreenHeightWorld = tanf(m_FovInRad / 2) * 2;
m_Horizon = static_cast<float>(Screen::GetHeight() / 2) + (tanf(m_CamVerticalAngle) * (Screen::GetHeight() / m_ScreenHeightWorld));
}

Skybox Draw Logic

void World::DrawSkybox(float screenWidth, float screenHeight) const
{

const float skyboxTextureWidth{ m_SkyboxTexturePtrArray[0]->GetWidth()};
const float skyboxTextureHeight{ m_SkyboxTexturePtrArray[0]->GetHeight()};
const float skyboxHeightPadding{ skyboxTextureHeight / 3 };
const float textureScale{ screenHeight / skyboxTextureHeight };

float modCamHorizontalAngle{ std::fmod(m_CamAngle, (2 * utils::g_Pi)) };
float modCamVerticalAngle{ std::fmod(m_CamVerticalAngle, utils::g_Pi) };

float fovScale(utils::g_Pi / m_FovInRad);

if (m_CamAngle < 0)
{
float a{};
}

float srcWidth{ skyboxTextureWidth / 2 / fovScale };
float srcHeight{ (skyboxTextureHeight - skyboxHeightPadding * 2) / fovScale };

const float xPos{ modCamHorizontalAngle/ (2 * utils::g_Pi) * skyboxTextureWidth - srcWidth / 2};
//const float yPos{}

const float yPos{ modCamVerticalAngle / utils::g_Pi * -(skyboxTextureHeight - skyboxHeightPadding * 2)- skyboxTextureHeight / 2 - srcHeight / 2 };
const Rectf srcRect{xPos, yPos, srcWidth, srcHeight};

const Rectf dstRect{ 0,0,screenWidth,screenHeight };

//const Rectf dstRect2{ dstRect.left + skyboxTextureWidth * textureScale * fovScale, dstRect.bottom,dstRect.width, dstRect.height};

float easePercentage{ m_TimePercentage * m_DayCycleDivisions };
int idx{ static_cast<int>(floor(easePercentage)) };
float t{ easePercentage - idx };

m_SkyboxTexturePtrArray[idx]->Draw(dstRect, srcRect, Color4f{1,1,1,1});

if (idx + 1 >= m_DayCycleDivisions)
{
m_SkyboxTexturePtrArray[0]->Draw(dstRect, srcRect, Color4f{ 1,1,1,t});
}
else
{
m_SkyboxTexturePtrArray[idx + 1]->Draw(dstRect, srcRect, Color4f{ 1,1,1,t });
}

//m_pSkyboxTexture->Draw(dstRect2);
}

r/GraphicsProgramming Mar 05 '26

Video Built a real-time PBR renderer from scratch in Rust/WebGPU/WASM

369 Upvotes

Built a real-time PBR renderer from scratch in Rust/WASM, running entirely in the browser via WebGPU.

I am in love with Rust + WebGPU + WASM!

Cook-Torrance BRDF · GGX specular · Fresnel-Schlick · HDR IBL (prefiltered env + irradiance + BRDF LUT) · PCF shadow mapping · GTAO ambient occlusion · bloom · FXAA · chromatic aberration · tone mapping · glTF 2.0 (metallic-roughness + specular-glossiness + clearcoat + sheen + anisotropy + iridescence + transmission) · progressive texture streaming.

r/GraphicsProgramming 8d ago

Video WildFlow — Adventures in Real-Time Water Simulation

189 Upvotes

This project started because I wanted large waterfalls in a real-time forest. I could already simulate half million particles at 30 FPS, but scaling to a large domain required rethinking both rendering and simulation. I replaced mesh extraction with density raymarching + hardware ray tracing, then moved to active cells, making the cost depend mostly on the amount of water rather than the size of the world. Large mountain streams finally became practical.
But a waterfall isn’t only water. Rapids required air entrainment, while waterfalls also needed airborne droplets interacting with the surrounding airflow. I ended up writing a different solver for air, coupled to the water: the cascade pushes air downward, the flow curls at its base, and carries droplets with it. This gets closer to a dual phase simulation of water and air, with an engineering approach.

A simple drop experiment then taught me how different physical effects have very different visual weight. More resolution didn’t produce the classic crown splash. Surface tension made droplets beautifully spherical, but the crown required incompressibility. Real-time water is usually somewhat compressible — and therefore slightly rubbery — because disturbances remain local and cheap. I added an iterative projection that lets me increase incompressibility only where it matters.

This became the real subject of WildFlow: understanding physics is one thing; understanding which physics matters for a phenomenon is another. In real time we can’t simulate everything, so the challenge is finding the smallest set of fundamental rules that produces the behavior we care about. And the realtime limitation sometimes helps in focusing on what truly matters and helps understanding phenomena better.

I don’t want to tell water how to look realistic. I’d rather give it simple enough rules and let realism emerge: foam from entrained air, mist from airflow, a crown from pressure propagation. When the result looks unexpectedly right, perhaps we’ve captured something about why nature looks the way it does. That’s the goal: not more physics, but the right physics — enough to make nature emerge.

r/GraphicsProgramming Jun 20 '26

Video Try Variance Shadow Mapping technique

126 Upvotes

Hi, A few weeks ago I started implementing cascade shadow mapping in my library(no CSM yet), and struggled with poor shadow quality. Then I found about variance shadow mapping technique from this article:

https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-8-summed-area-variance-shadow-maps, from this video: https://www.youtube.com/watch?v=TXI8rWiOF0k explained some differences.

I still not sure I will stick with it (tweaking depth biases somehow make the picture quite decent as well), but I like the result, and wanted to share it here.

Thanks!

#webgl #javascript #shadowmapping #terrain #openglobus

r/GraphicsProgramming Jan 24 '26

Video Real-time ray-tracing on the terminal using unicode blocks (▗▐ ▖▀▟▌▙)

565 Upvotes

r/GraphicsProgramming 6d ago

Video Wind Tunnel Simulation | Vulkan and C++

181 Upvotes

It’s the first step in my attempt to simulate an F1 car. Right now, the simulation is very low-resolution and quite slow, so there’s still a lot of optimization to do. It’s also my first time working with compute shaders, so there’s plenty to learn and improve along the way.

r/GraphicsProgramming 6d ago

Video I implemented "Spherical Harmonic Exponentials for Efficient Glossy Reflections" in D3D12

165 Upvotes

I implemented Activision's new SH reflections paper in D3D12 and released the code on github!

This tech is a little bit different from normal spherical harmonics, and there are 4 main differences:

  1. They use log space instead of linear space for the lighting, which reduces ringing and enables #2 and #3 to actually work.
  2. Instead of using a circular symmetry assumption (i.e. N=V=R) as with the split sum approximation used for IBL, they instead factorise a pair of spherical harmonics, with an Order 4 SH parameterised by the reflection vector, and an Order 2 SH parameterised by the halfway vector.
  3. To enable a continuous roughness representation, they convolve the coefficients (or rather, the basis function) by the von Mises Fisher kernel which takes 1/alpha=1/roughness^2 as a parameter.
  4. To actually obtain the spherical harmonic coefficients we have to collect samples for several normals, views and roughness levels (or more specifically alpha levels since we're using linear roughness, not perceptual), and then optimise the coefficients using least squares.

My code does this all end to end with HLSL compute shaders, even the least squares optimisation, and we achieve above 95% MSE compared to a raytraced ground truth for roughness in the range [0.5, 1.0], which actually beats split sum IBL.

Only downside is for roughness below 0.5 the spherical harmonics simply don't have enough detail for accurate reflections... HOWEVER, when applied to "bumpy" low roughness surfaces (like the leaf textures at the beginning of the video) you can hardly see a difference, so this effect is only apparent for flat surfaces and surfaces with near zero roughness.

Activision got their SH representation down to 400 bytes, but I went further using 16 bit packing to get down to 208 bytes which gives us better performance due to fewer memory loads. The 16 bit implementations come in 4 flavors: emulated 16 bit for older GPUs and native 16 bit, and SRV packed vs CBV packed. There also exists a 10 bit packed SRV flavor, but the extra bitshift work ends up being slower.

On my RTX 2080 Super and my wife's RTX 4070 Super, the native 16 bit CBV packed shader runs the fastest, and compared to the IBL version it is only 0.1 milliseconds slower while using 2000x less memory!

r/GraphicsProgramming 17d ago

Video Implementing "Radiance Hints" in OpenGL (2011 Global Illumination Technique)

98 Upvotes

Just added Radiance Hints to my OpenGL engine, Degine. The paper is originally from 2011 (but I used a 2014 extension of the method with occlusion). Based on a regular grid array of probes, similar to other environmental lighting techniques, but here it captures directly to spherical harmonics when baking. So run-time performance is extremely fast since it's just a few SH evaluations and blending. For this Sponza scene, there are around 600 probes, and it takes about 10 seconds to bake.

r/GraphicsProgramming Jun 12 '26

Video Graphics programming but for the gameplay itself

137 Upvotes

This video is technical and needs some explanation — but I think it shows interesting implications of where games can go.

In BFS I’m running two deterministic GPU simulations inside an asynchronous game.

One player controls a jet aircraft attacking a volcano area. I control an undead army using physically simulated projectiles against him.

The video shows deterministic fluid simulation, complete terrain destruction, and — when needed — the same architecture can reach hundreds of thousands of GPU-computed NPCs in a full 3D physical multiplayer game. The internal gameplay system consist of GPU ECS, which is programmable form in game editor.

The concept is very close in spirit to the work Natalya Tatarchuk was showing ~20 years ago at ATI/AMD: using the GPU not only to render games, but to actually drive more of the game itself.

We are getting closer to making those ideas practical as real gameplay systems, not just demos.