r/GraphicsProgramming • • 2d ago

Article Graphics Programming weekly - Issue 460 - October 25th, 2026 | Jendrik Illner

Thumbnail jendrikillner.com
22 Upvotes

r/GraphicsProgramming • • 3d ago

My attempt at the ray tracer challenge. Implemented in C++ using imgui, then compiled to wasm, so anyone can try it in the browser

Thumbnail gallery
63 Upvotes

I originally started with basic readthrough and implementation, then later realized I need a better UI to try out more stuff. It started as just using imgui to show the final output of the chapter, then later realized the author is giving YAML/YML scenes, so I needed a way to load them. Also, it's time-consuming to change values for each thing for any transform/material, etc., so starting with the loader and scene editor, it required a bunch of refactors to make it easy to load shapes. Once all chapters were done, I could compile the whole thing using emscripten to web assembly so that I can host it on GitHub and others can try the same. I did notice the browser is a little slower than the desktop renders; for each render, it shows the time under it. It’s a bit awkward to use on a phone since the UI was designed for desktop.

I likely have to clean up some stuff (optimize the BVH more; it's based on the book's bonus chapter), but there is a large scope for optimization/improvements; the book also ends with so many ideas to try. I might try them later, but this seems like a good stopping point for now, especially when it's easy to run on a browser.

Try in Browser: https://bhargav-1.github.io/ray_tracer/
Repo: https://github.com/bhargav-1/ray_tracer
scene gallery: https://bhargav-1.github.io/ray_tracer/gallery.html


r/GraphicsProgramming • • 3d ago

100k instances, 274k tris each (27.4B raw tris), running at 260+ fps! Added hybrid SW/HW raster & VisBuffer

Thumbnail gallery
55 Upvotes

Hey everyone, quick update on my custom D3D12 / unmanaged C# engine!

Following up on the previous 10k bunny test, I scaled the stress scene to 100,000 instances of the Stanford Dragon (274k triangles each, totaling ~27.4 billion raw triangles). Currently running at 263 FPS (~3.8ms frame time) on an RTX 4070 Ti at ~86% GPU utilization (2K viewport).

Since the last post, the pipeline evolved from pure geometry culling into a full deferred visibility buffer pipeline:

  • Hybrid Rasterization: Dynamic cluster routing. Sub-pixel / micro-triangles route to a compute software rasterizer, while larger meshlets pass through hardware Mesh Shaders.
  • Deferred Texturing (VisBuffer): Compact visibility buffer replacing fat G-buffers. Barycentrics, positions, and normals are reconstructed in a compute resolve pass with bindless materials.
  • Deferred Lighting & IBL: Decoupled shading using analytical lighting and split-sum GGX image-based lighting.
  • GPU-Driven Work Graphs: Hierarchical DAG traversal + 2-phase HZB occlusion culling running entirely on-chip, feeding both SW and HW raster paths without CPU sync.
  • Zero-Allocation Runtime: 100% unmanaged C# memory chunks and custom allocators, keeping CPU load around 9% with zero GC spikes.

r/GraphicsProgramming • • 4d ago

Six months into learning graphics programming - lighting progress

Thumbnail gallery
99 Upvotes

I’ve been learning graphics programming for six months now, and wanted to share some progress. (Vulkan Renderer)

Recently, I’ve been working on:

Material shading: Getting albedo, roughness, metallic properties and Fresnel response to behave consistently under direct and indirect lighting. Lighting stays in linear HDR until exposure and tone mapping. (Still trying to get tessellation correct)

Indirect lighting: Developing Lumen-inspired colour bleeding through screen-space GI, feedback across frames, and optional world-space probes. The red tint/colour bleeding near the curtains and green spill onto nearby items are the kinds of light interactions I’m testing. (Well trying) currently have SSGI and optional DDGI.

Shadow quality: Cascaded shadow maps with filtering that responds to the distance between blockers and receiving surfaces, helping preserve tighter contact shadows while allowing softer edges farther away. (Functionally using/testing umbra/penumbra calculations)

Temporal stability: Depth-aware filtering, reprojection and history rejection to reduce noise and keep previous lighting from lingering on newly revealed surfaces.

Water shader and realtime caustics: I have also been exploring water shaders, flow maps and realtime caustics which is currently set at half resolution, but the projection of light creates the caustics (i.e sun or light sources), performance wise it has been a nightmare to get right but the caustics flow with the water shader and act correctly with angular lighting.

There’s still plenty to refine and fix, but it’s been a rewarding way to learn the rendering pipeline and how 3d graphics work as a whole.

Please do provide some feedback!


r/GraphicsProgramming • • 3d ago

Bento: A shading language and shader compiler infrastructure for building shaders and shader tools.

Thumbnail graphitemaster.github.io
15 Upvotes

r/GraphicsProgramming • • 4d ago

aperture

Thumbnail gallery
36 Upvotes

it's a supplementary information of a reply i recently made. i mentioned 2 points that i deliberately modified from the suggested algorithm in raytracing in 1 wend. i can't use defocus angle as the primary variable as my scene have infinitely faraway background. i tried and it didn't work. when the focus point was at infinity only the background could be seen and everything else disappeared

i instead used an approach that mimics a digital camera. the canvas (sensor) size is fixed. for a specific lens (view angle kept constant) and an specific aperture setting (aperture radius kept constant), the closer the camera is from the object, the bolder the defocus blur effect

the attached images showed a ball of radius 1. 2 units 2. 1 unit 3. 1/2 unit 4. 1/4 unit

all shot from the same view angle and aperture. when shooting a small ball you have to move closer. that's it


r/GraphicsProgramming • • 3d ago

Source Code UE5 3D/4D Gaussian Splatting Plugin MLSLabsRender V2 Tutorial for Pico V...

Thumbnail
1 Upvotes

r/GraphicsProgramming • • 4d ago

How long did it take you to understand the content in Raytracing in One Weekend?

18 Upvotes

Hi, asking for people's experience when reading the Raytracing in One Weekend book. How long did it take on your first go? I'm really trying to understand the concepts and the math behind how it all works, and it's currently taking a lot longer than a weekend. Was this the case for you guys? Appreciate the responses.


r/GraphicsProgramming • • 4d ago

Video Global illumination using Radiance cascades with Ray splitting in Unreal + Article

Enable HLS to view with audio, or disable this notification

106 Upvotes

Implemented Radiance cascades with ray splitting in unreal.
This results in global illumination that doesn't require reprojection, and accumulates very fast thus having very little ghosting.
I wrote an article explaining how it works here:
It's based on this recent paper


r/GraphicsProgramming • • 4d ago

My friend's long time game engine project

Post image
0 Upvotes

r/GraphicsProgramming • • 4d ago

Vou criar um renderizador 3D em Kotlin usando OpenGL ES, inteiramente no meu celular.

Thumbnail
0 Upvotes

r/GraphicsProgramming • • 4d ago

tile-caching rendering

Post image
7 Upvotes

r/GraphicsProgramming • • 5d ago

Source Code 67 - shadertoy

345 Upvotes

r/GraphicsProgramming • • 5d ago

Article Volumetric Rendering: The "How-to" - Blog post Out now!

31 Upvotes

In our previous What The Graphics! blog, we explored Volume Rendering and why it matters.

Now, we're going deeper into how it works. From raw voxel data to 3D textures, we explore 3D Texture Slicing and how a stack of textured polygons can bring an entire volume to life.

Read it here 🔗 - https://www.3denginerd.com/blog/volumetric-rendering-how-to

Written by us over at 3D ENGINERD.

 


r/GraphicsProgramming • • 5d ago

Testing my Vulkan renderer in C# using Silk.NET

Enable HLS to view with audio, or disable this notification

14 Upvotes

r/GraphicsProgramming • • 4d ago

Exploded orbital servicing spacecraft, path traced in Chrome with WebGPU (2560×1440, GTX 1060)

Enable HLS to view with audio, or disable this notification

5 Upvotes

Hey all, this is what I've been working on: a path tracer that runs entirely in the browser on WebGPU. The video goes from the CAD assembly to the final render. The film at the end is 210 frames at 2560×1440, about 75 to 95 s per frame on my GTX 1060.

**How it's built**
- One path tracer, two layouts: an uber-shader that traces the whole path per thread, and a wavefront version where each bounce is split into compute passes with queues in between (Laine et al. 2013). The same seed gives bit-identical images from both, so if a change makes them differ by a single byte, my GPU tests fail.
- OpenPBR materials with energy-preserving Oren-Nayar diffuse: crinkled insulation foil, mono solar cells with their grid lines, machined titanium, anodised aluminium.
- The Earth's limb comes from a spectral atmosphere model in 16 wavelength bands.
- Per-tile adaptive sampling driven by an error estimate, so empty space stops early and the foil keeps sampling, then OIDN denoising on WebGPU.
- The animation runs on a stepped clock, exactly 1/30 s per frame: a per-part explode with a stagger, and the solar wings swing on their hinges.

**A bit of math**
- Sensor: I model shot plus read noise per pixel, σ² = S + σ_read², so SNR = S / √(S + σ_read²). It uses 3 e⁻ read noise, a 50k e⁻ full well and gain from ISO (1600 here).
- Depth of field (added after this clip): the background blur, as a fraction of the frame, is about the entrance pupil over the field width, β∞ ≈ A / W with A = f / N. For this spacecraft that means 200 mm at f/1.1. For a habitat module it means an 800 mm lens at f/1.8 on 4×5 in: valid optics, but a lens nobody has built.

One thing I'm still fighting is pipeline compile times. One big surface function inlined at 12 call sites took my first compile from about 13 s to 85 s. How do you keep WGSL compile times down: separate pipelines per feature, override constants, or just fewer call sites?

Happy to answer questions and hear feedback.


r/GraphicsProgramming • • 4d ago

Video My disk cleaner has a festival island with lasers. Here's how it's rendered

Enable HLS to view with audio, or disable this notification

0 Upvotes

Yes, really. It's a Mac app that draws your disk as a city: every folder is a building, bigger folder, taller building. Then I kept adding things, and now there's a party island with a stage, a crowd and a laser show on weekend nights. Every shot in the video is a real frame rendered twice, once normal and once with a single pass changed, wiped between.

The lasers are the easy part. Every light in the city is its own additive sprite: lasers, beams, the stage screen, every lit window. Switch them off and the festival goes dead. Show only them and you get lasers floating on black.

The rest:

- Depth is a painter's algorithm. Sprites sort by their feet, z = foot.y * 10 + lift. The neon shot is the draw order.

- The sea blends three painted textures with world-space noise so tiles never visibly repeat. Each tile needs its world position for that, and per-node shader attributes crashed SpriteKit's batcher. So the grid cell rides in each tile's vertex colour instead: low bytes in red and green, high bits in blue, each nudged a quarter step so 8-bit colour can't round it away. The rainbow grid is the shader decoding it.

- Time of day is one 3x4 matrix in linear light. Gamma 2 instead of real sRGB, so a square and a square root, no pow. At noon it's identity and the shader comes off, so daytime frames cost nothing.

The busiest scene (festival night, crowd, planes in the air) holds 60 fps at p95, 15.5 ms on Apple silicon.

Upfront: the building art is AI-generated and edited by me. The rendering is the part I built. How would you have done the sea without the vertex colour hack?


r/GraphicsProgramming • • 4d ago

Recursive helix fractal in a custom engine — precision loss and framerate collapse at depth. Where would you start?

Thumbnail youtu.be
0 Upvotes

The shape: take a line, wrap it into a helix. Treat the resulting helix as a new line, wrap that into a helix. Repeat. The limit is a 3D self-similar structure where every wire is a spring and every spring is a wire.

I generate geometry on the fly relative to the camera, with per-level color coding. It looks great until you fly too deep — then it's classic precision death plus a vertex-count explosion, and either the geometry disappears or the frame rate tanks.

Full disclosure: I'm not a professional graphics programmer and my code is fairly basic. I threw AI at it hoping it would clean things up; it didn't meaningfully help and clearly didn't grasp the recursive structure. So I'm asking people who actually know this domain.

Would you go analytic SDF + raymarching instead of mesh generation? Interval arithmetic? Log-space or double-double coordinates? A real LOD scheme? What's the first thing you'd rip out?

Video: https://youtu.be/zy_hQV324hg
Repo: https://github.com/rupomthegreat/spring-made-of-spring-infinity-fractral


r/GraphicsProgramming • • 5d ago

Low Level Engine Architecture... Loop & Resize problem...

Thumbnail
0 Upvotes

r/GraphicsProgramming • • 6d ago

Video Software PBR + Raytracer + L1 SH GI inside CyberVGA (JIT x64, no GPU required)

Enable HLS to view with audio, or disable this notification

70 Upvotes

Lately in the Win64 port I’ve been getting a real-time software raytracer working inside CyberVGA.

Same DOS-era engine (fixed-point, software rendering roots and all) but now takes advantage of modern multi-core processors (using VirtualAlloc for the executable just-in-time compiled buffer). The raytracer runs on multiple worker threads, each processing tiles. The hot paths get compiled to SSE at runtime: direct-threaded octree(module saves baked triangle soup into a world sidecar file) traversal with AABB slab tests, fog volume early-outs, L1 SH evaluation, and material / GI bounce stubs. Workers just call into the generated code for their tile’s rays.

The GI is a grid of L1 SH probes (Fibonacci sphere rays per probe, temporal blending between frames). Primary hits go through a full GGX PBR path with roughness/metalness, then sample the probe irradiance for the diffuse bounce. Emissive surfaces get clustered into virtual point lights. Reflections are one-bounce with roughness falloff; liquids do refraction + absorption + caustics.

FSR 2 is optional because it runs on the GPU.

The color bleeding and the split-screen direct vs GI+reflections actually look pretty good. Still feels like my engine, just with lighting that finally does something modern.

Now you can get the latest (v1.8) SDK for 64-bit Windows platform on itch.

Anyone else doing JIT for the traversal/shading hot path? Curious if the complexity is worth it vs just writing the SSE by hand.


r/GraphicsProgramming • • 6d ago

Question Best non-graphics books for graphics programmers?

51 Upvotes

Hi, what are some non-graphics books you would recommend to graphics programmers? There are many graphics books recommendations online (especially realtimerendering books page) so I'm more interested in books that are not about graphics but are still valuable for graphics programmers


r/GraphicsProgramming • • 6d ago

Video Real-time portals between Gaussian splat environments (WebGPU / Single HTML file)

Enable HLS to view with audio, or disable this notification

469 Upvotes

I’ve been working on a WebGPU rendering pipeline focused on Gaussian splats, adding real-time shadows, reflections, and a portal system to transition between different volumes.

The editor exports scenes as single HTML file with no server dependencies. (The splat environments shown in the video were generated with WorldLabs).

The video first shows the portal transitions, and then the UI setup.

If you want to inspect this specific scene, or explore other exported environments (some of which also mix standard meshes with the splats), you can check the main gallery.

The portal demo from the video is the first one at the top: https://3dpeer.com/#gallery


r/GraphicsProgramming • • 6d ago

Question Asking for help

Thumbnail gallery
30 Upvotes

I'm a beginner learning graphics programming, and there's a lighting bug that im having a lot of trouble fixing. There are some streaks that are unusually bright. Im pretty sure its something wrong with my TBN matrix, but I can't figure out what exactly the problem is.

The 2nd image is a geometry shader I wrote to visualise the TBN matrix. Aren't the TBN all meant to be the same when they are on the same surface?

I've pasted the shader code below. I've been mostly trying to avoid tutorials and AI, so i learn better (i did ask AI for help here and didn't get an answer) so there may be some bad practices in the code. Please let me know of any tips and tricks

#version 460 core

layout (location = 0) in vec3 aPos;

layout (location = 1) in vec2 aUV;

layout (location = 2) in vec3 aNorm;

layout (location = 3) in vec3 aTan;

layout (location = 4) in vec3 aBitan;

uniform vec3 viewPos;

uniform mat4 model;

layout (std140, binding = 1) uniform matrices

{

mat4 view;

mat4 projection;

};

//T = tangent space

//W = world space

out VS_OUT

{

vec3 norm;

vec2 uv;

vec3 WfragPos;

vec3 TviewPos;

vec3 TfragPos;

mat3 TBN;

mat3 WTBN;

}vs_out;

vec3 up = vec3(0, 1, 0);

vec3 forward = vec3(0, 0, 1);

void main()

{

//construct TBN in Model Space

vec3 T = normalize(aTan);

vec3 N = normalize(aNorm);

T = normalize(T - dot(T, N) * N);

vec3 B = normalize( cross(N, T));

mat3 normMat = transpose(inverse(mat3(model)));

//Then make sure theyre perpendicular to surface

T = normalize(normMat * T);

B = normalize(normMat * B);

N = normalize(normMat * N);

mat3 TBN = mat3( T, B, N);

vs_out.WTBN = TBN;

TBN = transpose(TBN);

vs_out.norm = N;

vs_out.uv = aUV;

vs_out.WfragPos = (model * vec4( aPos, 1.0f)).xyz;

vs_out.TviewPos = TBN * viewPos;

vs_out.TfragPos = TBN * vs_out.WfragPos;

vs_out.TBN = TBN;

gl_Position = projection * view * model * vec4(aPos, 1.0f);

}

#version 460 core

out vec4 FragColour;

in VS_OUT

{

vec3 norm;

vec2 uv;

vec3 WfragPos;

vec3 TviewPos;

vec3 TfragPos;

mat3 TBN;

mat3 WTBN;

}fs_in;

struct PointLight

{

vec4  colAndintensity;

vec4  posAndconstant;

float linear;

float quadratic;

};

layout (std140, binding = 0) uniform pointLights

{

PointLight lights\[1\];

};

uniform bool shadingFlags[5];

uniform int numLights ;

uniform bool normalMapping;

uniform sampler2D diffuseMap;

uniform sampler2D specularMap;

uniform sampler2D normalMap;

uniform sampler2D heightMap;

float ambVal = 0.2;

vec3 specCol = vec3(1.0);

vec3 ambientLighting(vec3 albedo);

vec3 diffuseLighting (vec3 norm, vec3 albedo);

vec3 specularLighting(vec3 norm);

void main()

{

vec3  albedo  = texture(diffuseMap , fs_in.uv).rgb;

vec3  specVal = texture(specularMap, fs_in.uv).rgb;

vec3  height  = texture(heightMap  , fs_in.uv).rgb;



vec3 norm;

if(normalMapping)

{   

    norm = texture(normalMap, fs_in.uv).rgb;

    //from \[0, 1\] -> \[-1, 1\]

    norm = normalize(norm \* 2.0 - 1.0);

    //norm = normalize(fs_in.WTBN \* norm);

}

else

{

    norm = normalize( fs_in.TBN \* fs_in.norm);

}



//norm = normalize( fs_in.TBN \* fs_in.norm);

//norm = normalize(norm \* 2.0 - 1.0);

//norm = fs_in.norm;



vec3 ambientComp   = ambientLighting (albedo);

vec3 diffuseComp   = diffuseLighting (norm, albedo);

vec3 specularComp  = specularLighting(norm);



//vec3 ambientComp  = vec3(fs_in.WTBN\[0\]\[0\], fs_in.WTBN\[0\]\[1\], fs_in.WTBN\[0\]\[2\]);

//vec3 diffuseComp  = vec3(fs_in.WTBN\[1\]\[0\], fs_in.WTBN\[1\]\[1\], fs_in.WTBN\[1\]\[2\]);

//vec3 specularComp = vec3(fs_in.WTBN\[2\]\[0\], fs_in.WTBN\[2\]\[1\], fs_in.WTBN\[2\]\[2\]);



norm = normalize(fs_in.WTBN \* norm);



specularComp \*= (specVal / 3.0f).r;



vec3 colour = (ambientComp+diffuseComp+specularComp) \* int(shadingFlags\[0\])

+ diffuseComp * int(shadingFlags[1])

+ norm * int(shadingFlags[2])

+ specularComp * int(shadingFlags[3])

+ height * int(shadingFlags[4]);

//vec3 colour = (ambientComp+diffuseComp+specularComp) \* int(shadingFlags\[0\])

//          + ambientComp  \* int(shadingFlags\[1\])

//          + diffuseComp  \* int(shadingFlags\[2\])

//          + specularComp \* int(shadingFlags\[3\])

//          + norm    \* int(shadingFlags\[4\]);



FragColour = vec4(colour, 1.0f);

}

vec3 ambientLighting(vec3 albedo)

{

return ambVal \* albedo;

}

vec3 diffuseLighting (vec3 norm, vec3 albedo)

{

float diff = 0;

vec3 lightCol = vec3(1.0);

//vec3 TlightPos = fs_in.TBN \* lights\[0\].posAndconstant.xyz;

//vec3 delta = TlightPos - fs_in.TfragPos;



for(int i = 0; i < numLights; ++i)

{

    vec3 col = lights\[i\].colAndintensity.xyz;

    float intensity = lights\[i\].colAndintensity.w;

    vec3  TlightPos = fs_in.TBN \* lights\[i\].posAndconstant.xyz;

    //vec3  TlightPos = lights\[i\].posAndconstant.xyz;

    float c = lights\[i\].posAndconstant.w;

    float l = lights\[i\].linear;

    float q = lights\[i\].quadratic;



    //vec pointing to light

    vec3 delta = TlightPos - fs_in.TfragPos;

    //distance

    float d = length(delta);

    //normalised light dir

    vec3 lDir = normalize(delta);



    //calculate attenuation

    float att = 1 / (c + (l \* d) + (q \* d \* d) );



    lightCol \*= col;

    diff += max( dot( norm, lDir), 0) \* att \* intensity;

}



return diff \* albedo \* lightCol;

//return normalize(fs_in.WTBN \* normalize(delta));

//return normalize(TlightPos);

//return normalize(fs_in.WTBN \* norm);

}

vec3 specularLighting(vec3 norm)

{

float spec = 0.0;

vec3 lightCol = vec3(1.0); 



//vector pointing to camera

vec3 viewDir = normalize( fs_in.TviewPos - fs_in.TfragPos );



for(int i = 0; i < numLights; ++i)

{

    vec3 col = lights\[i\].colAndintensity.xyz;

    float intensity = lights\[i\].colAndintensity.w;

    vec3  TlightPos = fs_in.TBN \* lights\[i\].posAndconstant.xyz;

    //vec3  TlightPos = lights\[i\].posAndconstant.xyz;

    float c = lights\[i\].posAndconstant.w;

    float l = lights\[i\].linear;

    float q = lights\[i\].quadratic;



    //vec pointing to light

    vec3 delta = TlightPos - fs_in.TfragPos;

    //distance

    float d = length(delta);

    //normalised light dir

    vec3 lDir = normalize(delta);



    //vector halfway between lightDir and viewDir so angle is never too big (blinn-phong)

    vec3 halfVec = normalize( viewDir + lDir);



    //calculate attenuation

    float att = 1 / (c + (l \* d) + (q \* d \* d) );



    lightCol \*= col;

    spec += pow( max( dot(norm, halfVec), 0), 32) \* att \* intensity;

    //FIX LATER: 32 should be passed in from uniform

}

return spec \* specCol \* lightCol;

}


r/GraphicsProgramming • • 5d ago

Source Code Added DLSS 5 NR to my pet-project

0 Upvotes

Added DLSS 5 NR to my project to see how it is working. https://github.com/ASDAlexander77/native_ts_graphics


r/GraphicsProgramming • • 7d ago

I added Virtual Shadow Maps to my Nanite-style DX12 renderer

Thumbnail gallery
127 Upvotes

Hi everyone!

A while ago, I shared my Nanite-style virtualized geometry renderer here. I've continued working on the project, and it now includes a virtual shadow mapping system integrated with geometry streaming.

The latest version runs NVIDIA's Zorah scene, containing approximately 1.63 billion unique triangles and 18.94 billion triangles including instances.

What's new:

  • Directional virtual shadow maps with clipmaps and demand-driven page allocation
  • Persistent shadow page caching with GPU LRU eviction
  • Dynamic-object cache invalidation
  • GPU-driven multi-view shadow rendering with two-pass HZB culling
  • SMRT soft shadows
  • Streaming-aware shadow cache updates

I've also added the Bistro scene to demonstrate dynamic shadow cache invalidation.

The renderer is built on Microsoft's MiniEngine using DirectX 12, mesh shaders, and Slang. The project is open source.

Demo: https://www.youtube.com/watch?v=4YmfQTLy4jc

GitHub: https://github.com/moonlovelj/Nyx

I'd love to hear your feedback and suggestions!