Skip to content

Playing with path tracing in Unity engine using compute shaders

License

Notifications You must be signed in to change notification settings

teamclouday/PathTracer

Repository files navigation

Path Tracer

My path tracer implemented in Unity engine


Basic Scene

Expand for Details

Built based on the tutorial. Only contains a ground and multiple spheres with skybox.
Compiled executables available here

basic

Cornell Box

Expand for Details

Compiled executables available here

Improved hemisphere sampling adapted from lwjgl3-demos.
A better random value generator.
Support unity material _EMISSION, _EmissionColor, _Metallic, _Glossiness values.

cornellbox

Cornell Box & Bunny

Expand for Details

Compiled executables available here

Added basic BVH (bounding volume hierarchy).
Scene Info:

BVH tree nodes count = 290135
Total vertices = 100277
Total indices = 435474
Total normals = 100277
Total materials = 10

RTX2060S has about 18fps at default view position in unity editor mode
Looking forward to further optimize it.

cornellboxbunny

Dragon

Expand for Details

Compiled executables available here

Added reflection & refraction workflow for transparent materials.
In my implementation, if a material (standard shader) render mode is not opaque, it will go through this workflow. In this case, smoothness is translated to index of refraction (ior):

k => k * 2.0 + 1.0

Scene Info:

BVH tree nodes count = 1735017
Total vertices = 439077
Total indices = 2614194
Total normals = 439077
Total materials = 3

Loading time is very slow. Need to optimize BVH tree construction.

dragon

Cornell Box & Buddha

Expand for Details

Compiled executables available here

Added openimagedenoise, so that when the scene cannot converge, the output image is smooth.
Press Left CTRL + V to toggle denoiser, default is off.

Scene Info:

BVH tree nodes count = 2164457
Total vertices = 550046
Total indices = 3265248
Total normals = 550046
Total materials = 10

Expect a long loading time.

Without denoiser (412 samples):
cornellboxbuddha_S412

With denoiser (195 samples):
cornellboxbuddha_S195

Side Note:
After multiple testing in this environment setup, it seems that with a colored skybox (not dark in this case), the scene converges much faster. With a dark environment and only one small emissive light object, the scene converges very slow. The reason behind it, in my opinion, is because during random sampling, the ray hits a dark non-emissive object much more frequently than hitting an emissive object. Therefore, the samples contain many dark pixels because the ray is not lucky enough to reach a light source. A denoiser is required to improve the visual in this case.

Bunny

Expand for Details

Compiled executables available here

No new features added. Fixed an important bug that occurs during cosine weighted hemisphere sampling. Switched to another random value generator that is more convenient. Finally, improve the transparent workload for better visual effects. (Not refering to any paper so not physically accurate)

Denoised view:
bunny

Side Note:
As you may have noticed in previous "Cornell Box & Buddha" demo images, the head light in the scene casts light in biased directions. This is caused by a bug in sampling function, which is partially fixed in this new scene. Can refer to here for details. The reason I say it's partially fixed is because though the area light looks fine when it is large, it is still not perfect when it is a small light. In fact, no matter of its geometric shape, it will tend to scatter a cross shape distribution of light on the ground.

Depth of View

Expand for Details

No executable available, because it is meant to be tested in Unity editor.

Updated camera model, with focal length and aperture.

Denoised view:
bunny_camera

Paper Effect

Expand for Details

This is done by playing with rng_initialize:

float2 center = float2(id.xy);
rng_initialize(dot(center, camera.offset), _FrameCount);

where camera.offset is just another vector of independent random values.

The result looks as if it is drawn on a paper, and it is cool without any denoising:
paperbunny

Sponza

Expand for Details

Compiled executables available here

Added SAH to improve BVH reference efficiency.
Added support for albedo texture maps. Textures are first combined to a Texture2DArray object and then bound to compute shaders. Each texture is resized to the max size of all textures.

Scene Info:

TLAS nodes = 395
BLAS nodes = 501469
Total vertices = 192254
Total indices = 786873
Total normals = 192254
Total materials = 396
Total textures = 24

Expect a low fps (about 3-5).

Denoised views:
sponza_lion
sponza_down

Room

Expand for Details

Compiled executables available here

Support emission maps and metallic maps.
Support cutoff render mode (skip geometry if alpha < 1.0).
Added bvh build for TLAS (but not used in this scene, see side note).
Added sRGB color space conversion for texture maps.
Change camera fov and add keyboard combination for material reloading.
Support directional light in the scene (regarded as sun light), and tweak the lighting for transparent materials.

Scene Info:

TLAS nodes = 25
TLAS raw nodes = 45
BLAS nodes = 1225193
Total vertices = 469711
Total indices = 4042797
Total normals = 469711
Total materials = 46
Total albedo textures = 2
Total emissive textures = 0
Total metallic textures = 0

Expect a low fps.

Denoised view:
room

Side Note:
My previous implementation regards TLAS nodes as an array. For each ray, it loops the full array, tests intersections with bounding volumes and enters BLAS nodes if hit. In scenes such as Sponza, number of TLAS nodes can be large. Therefore, I created another BVH for TLAS nodes, and the ray first recurse in the TLAS tree to find a hit and then enter the corresponding BLAS node. However, based on my experiments, this modification makes rendering even slower. The reason is probably because each node in TLAS tree may have overlapping bounding areas for left and right children. This potentially increases the amount of intersection tests in intermediate nodes that are not leaves. (which affects BLAS tree as well) I think the next improvement is to find a space partition strategy for geometries that reduces overlapping areas to minimum.

Exterior

Expand for Details

Compiled executables available here

Support normal maps and roughness maps (for Autodesk interactive shader materials).
Possible to adjust directional light rotation at runtime.
Now able to toggle between Unity renderer and Path tracer. It is recommended to move camera and adjust light direction in Unity renderer mode and then switch back to Path tracer.

Scene Info:

TLAS nodes = 2973
TLAS raw nodes = 1615
BLAS nodes = 4821155
Total vertices = 2921248
Total indices = 8500071
Total normals = 2921248
Total tangents = 2921248
Total materials = 1616
Total albedo textures = 106
Total emissive textures = 6
Total metallic textures = 0
Total normal textures = 86
Total roughness textures = 0

Expect a low fps and the longest loading time. Do not launch with a large window size, or DirectX may crash.

Denoised views:
exterior_v1
exterior_v2
exterior_v3
exterior_v4

Fireplace Room

Expand for Details

Compiled executables available here

Modified rendering equations based on Disney BSDF and refering to online resources.
Added support for multiple point lights, with customized illumination formulas.
Now able to toggle camera depth of view, and allow camera focus by middle mouse click.
Fixed crucial bug in denoiser, and added another optional realtime denoiser with spatial filter shader.

Scene Info:

TLAS nodes = 43
TLAS raw nodes = 24
BLAS nodes = 261608
Total vertices = 190085
Total indices = 429135
Total normals = 190085
Total tangents = 190085
Total materials = 25
Total albedo textures = 4
Total emissive textures = 0
Total metallic textures = 0
Total normal textures = 0
Total roughness textures = 0

Denoised views:
fireplace1
fireplace2


Controls

W -> camera forward
S -> camera backward
A -> camera left
D -> camera right
UP -> light rotation X increases
DOWN -> light rotation X decreases
RIGHT -> light rotation Y decreases
LEFT -> light rotation Y increases
ESC -> quit application
Left click and drag -> camera look around
Scroll up -> move forward
Scroll down -> move backward
Left CTRL + X -> save screenshot in data folder
Left CTRL + V -> toggle denoiser (default is off)
Left CTRL + R -> Reload materials and light info (editor only)
Left CTRL + SPACE -> Switch between Unity renderer and Path tracer
Left CTRL + C -> toggle camera depth of view
Middle Mouse Click -> focus on current position (only when camera depth is enabled)

References

GPU Ray Tracing in Unity
Physically Based Rendering
RadeonRays_SDK
GLSL-PathTracer
Another View on the Classic Ray-AABB Intersection Algorithm for BVH Traversal
Spatial Splits in Bounding Volume Hierarchies
Recursive SAH-based Bounding Volume Hierarchy Construction
Ray Tracing: The Next Week
Casual Shadertoy Path Tracing 3: Fresnel, Rough Refraction & Absorption, Orbit Camera