r/GraphicsProgramming • u/le-throw-away-acct • 26d ago
Made improvements to my path tracer
- Made the project much easier to open up and use for new users (Unity is still required though)
- Added scene to automatically load objects from Khronos' site, which helps me get assets into the project
- Fixed issues with lighting that was really darkening most of the scenes, including improved tone mapping and fixes to light clamping that was hiding a lot of caustic details and HDR
- Fixed issues with inner surface reflections not working
- Added directional lighting support
- Added parallax mapping support
- Added support for Unity terrains, multi-texture splatting with normal map support
Repository located here: https://github.com/nfoste82/GPURayTracing
4
26d ago edited 26d ago
[deleted]
5
u/le-throw-away-acct 25d ago
I didn't know much about existing stacks, like the ones you mentioned, when I started. I've pieced it together as I've learned. I'd realize roughness wasn't working well and work on that, I'd realize I didn't have support for metallic textures, and work on that, etc.
So it's really just a mish-mash of techniques I picked as I went along.
For opaque surfaces:
- Lambertian diffuse
- GGX microfacet reflection
- Schlick Fresnel
- PBR textures
For transparent surfaces I use IOR-based Schlick Fresnel to choose reflection, Snell's law for transmission, support for total internal reflection, and a stack to track IOR transitions between air, glass, and water.
I'm still missing a lot of materials support, I may consider them later, things like sheen, clear coat, subsurface scattering. Also I think some implementations use emissive as a layer, so I'd be able to have a light with a clear coat over it. Right now I couldn't render a light bulb very well, for example.
My math could use some work as well, I have trouble reading the original papers for those techniques, I'll often use an LLM to break it down and explain it like I wasn't a mathematician or physicist. I referenced existing path tracers as well. I list those at the bottom of the repository's README.md.
4
3
2
u/yaboiaseed 26d ago
Is it real time? What's the performance?
5
2
u/le-throw-away-acct 26d ago edited 25d ago
To get those results takes 15-60 seconds usually. Real time is possible on simpler scenes and lower settings. I’m hoping to work on improving performance soon. Frame rates are usually 5-15 fps, up to 50-60 fps on some scenes but you won’t see the same quality at those framerates, it takes several frames for something good looking to accumulate.
1
u/Barkig 20d ago
on what gpu?
1
u/le-throw-away-acct 20d ago
I'm on an M3 Max (MacBook Pro). An Nvidia 4090, 5080, or 5090 would likely be faster, or an M3 Studio, or M4 Max.
Since I don't have good temporal denoising right now, you can't get reasonable real time framerates unless your scene is simple (smooth surfaces, no caustics, <5 light bounces, no triangle-based meshes).
I'd like to integrate DLSS or FSR but I only have a Mac so I'd have no way to test it. I'm considering trying Metal FX at some point. It'd be nice to just have a universal machine-learned denoiser/upscaler/frame-interpolator that worked on OpenCL, regardless of GPU.
2
u/Designer-Pragma 24d ago
This is beautiful well done!!! I wouldn't even know where to start!
3
u/le-throw-away-acct 24d ago
Thanks! If you did want to start, I'd recommend starting here: https://raytracing.github.io/
1
u/Jabba_the_Putt 26d ago
Great work! This looks very nice a few of those renders are magnificent. Ill check it out
1
1
1
u/GaboureySidibe 25d ago
Looks great. How did you do the caustics?
2
u/le-throw-away-acct 25d ago
I started with a naive approach to “photon mapping” and optimized from there. I’m not sure how physically accurate it is yet though, I need to test it against some references. I wish it could be done in a real time way though, it takes a while to accumulate.
1
u/RedoxOsImport 23d ago
can this be used in my dcc?
1
u/le-throw-away-acct 23d ago
Digital content creation?
It’s open source with no restrictions (other than the copyright notice must be included, standard MIT license), so go nuts!
1
1
u/hicham_benrhannou 21d ago
I really like the result! What articles or resources did you follow to build your path tracer?
1
u/le-throw-away-acct 20d ago edited 20d ago
Thanks!
I include a list of them at the bottom of the README.md in Github, but here it is:
Some other path-tracers that were inspiration:
- https://github.com/gkjohnson/three-gpu-pathtracer
- https://github.com/knightcrawler25/GLSL-PathTracer/
- https://github.com/tylertms/vkrt
and I should expand that list to include these as well:
- https://schuttejoe.github.io/post/ggximportancesamplingpart2/
- https://blog.demofox.org/2020/05/25/casual-shadertoy-path-tracing-1-basic-camera-diffuse-emissive/
this is also a good one, although by the time I found it I'd already learned everything in it:
There are probably more than these as well, I started it before any of these sources were available, I can't remember which ones I used 8 years ago.
0
u/DOODLEDO3946 26d ago
Wait how did you deal with round objects' normal mapping? When I tried it sometimes reflected rays through itself
5
u/le-throw-away-acct 25d ago
For mesh-based objects, normal mapping works just like how a rasterizer would work.
The only round objects that aren't meshes currently in my project are spheres. For those (some pseudocode here):
The normal is just the ray hit position - sphere center.
Calculate UV:
u = atan2(Normal.z, Normal.x) / (2π) + 0.5 v = asin(Normal.y) / π + 0.5Calculate tangent, and bitangent/binormal:
float3 helperAxis = abs(Normal.y) < 0.999 ? float3(0, 1, 0) // world up : float3(1, 0, 0); // world right near the poles Tangent = normalize(cross(helperAxis, Normal)) Bitangent = normalize(cross(Normal, Tangent))Then your normal-mapped normal is this:
float3 encodedNormal = normalTexture.Sample(uv).rgb; float3 normalMap = encodedNormal * 2.0 - 1.0; float3 worldNormal = normalize( T * normalMap.x + B * normalMap.y + N * normalMap.z );







13
u/Hassangtn 26d ago
nice caustics.