-
Notifications
You must be signed in to change notification settings - Fork 774
/
PathTracingMain.raytrace
162 lines (128 loc) · 7.01 KB
/
PathTracingMain.raytrace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// We need N bounces given that we want to support complex light paths
#pragma max_recursion_depth 11
// HDRP include
#define SHADER_TARGET 50
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Builtin/BuiltinData.hlsl"
// Ray tracing includes
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RayTracing/Shaders/Common/AtmosphericScatteringRayTracing.hlsl"
// We need this for the potential volumetric integration on camera misses
#define HAS_LIGHTLOOP
// Path tracing includes
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingIntersection.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl"
// Input(s)
float4x4 _PixelCoordToViewDirWS;
int _RaytracingCameraSkyEnabled;
float4 _RaytracingCameraClearColor;
TEXTURE2D_X(_SkyCameraTexture);
// Output(s)
RW_TEXTURE2D_X(float4, _FrameTexture);
// DoF related parameters
float4 _PathTracedDoFConstants; // x: aperture radius, y: focus distance, zw: unused
[shader("miss")]
void MissCamera(inout PathIntersection pathIntersection : SV_RayPayload)
{
bool skyEnabled = _EnvLightSkyEnabled && _RaytracingCameraSkyEnabled;
float4 missColor = skyEnabled ? _SkyCameraTexture[COORD_TEXTURE2D_X(pathIntersection.pixelCoord)] : _RaytracingCameraClearColor;
pathIntersection.value = missColor.xyz * GetInverseCurrentExposureMultiplier();
pathIntersection.alpha = missColor.w;
ApplyFogAttenuation(WorldRayOrigin(), WorldRayDirection(), pathIntersection.value, pathIntersection.alpha);
if (_EnableVolumetricFog && _RaytracingMinRecursion <= 1)
{
float3 envValue = pathIntersection.value;
// Generate a 4D unit-square sample for this depth, from our QMC sequence
float4 inputSample = GetSample4D(pathIntersection.pixelCoord, _RaytracingSampleIndex, 0);
// Compute volumetric scattering
pathIntersection.value = 0.0;
pathIntersection.t = FLT_MAX;
float pdf = 1.0;
bool sampleLocalLights;
if (SampleVolumeScatteringPosition(inputSample.w, pathIntersection.t, pdf, sampleLocalLights))
{
ComputeVolumeScattering(pathIntersection, inputSample.xyz, sampleLocalLights);
// Apply the pdf
pathIntersection.value /= pdf;
// Apply volumetric attenuation
ApplyFogAttenuation(WorldRayOrigin(), WorldRayDirection(), pathIntersection.t, pathIntersection.value);
}
// Reinject the environment value
pathIntersection.value += envValue;
}
}
[shader("miss")]
void MissLight(inout PathIntersection pathIntersection : SV_RayPayload)
{
}
[shader("miss")]
void MissMaterial(inout PathIntersection pathIntersection : SV_RayPayload)
{
if ((_RaytracingMaxRecursion - pathIntersection.remainingDepth) < _RaytracingMinRecursion)
{
pathIntersection.value = 0.0;
return;
}
pathIntersection.value = _EnvLightSkyEnabled ? SampleSkyTexture(WorldRayDirection(), 0.0, 0).xyz : 0.0;
ApplyFogAttenuation(WorldRayOrigin(), WorldRayDirection(), pathIntersection.value);
}
[shader("raygeneration")]
void RayGen()
{
uint2 LaunchIndex = DispatchRaysIndex().xy;
// Get the current pixel coordinates
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Jitter them (we use 4x10 dimensions of our sequence during path tracing atm, so pick the next available ones)
float3 jitteredPixelCoord = float3(currentPixelCoord, 1.0);
jitteredPixelCoord.x += GetSample(currentPixelCoord, _RaytracingSampleIndex, 40);
jitteredPixelCoord.y += GetSample(currentPixelCoord, _RaytracingSampleIndex, 41);
// Compute the ray direction from those coordinates (for zero aperture)
float3 directionWS = -normalize(mul(jitteredPixelCoord, (float3x3)_PixelCoordToViewDirWS));
float3 cameraPosWS = GetPrimaryCameraPosition();
float apertureRadius = _PathTracedDoFConstants.x;
if (apertureRadius > 0.0)
{
// Compute the ray origin and direction for a lens with non-zero aperture
// Sample the lens apperture using the next available dimensions (we use 40 for path tracing, 2 for sub-pixel jittering, 64 for SSS -> 106, 107)
float r1 = GetSample(currentPixelCoord, _RaytracingSampleIndex, 106);
float r2 = GetSample(currentPixelCoord, _RaytracingSampleIndex, 107);
float2 uv = apertureRadius * SampleDiskUniform(r1, r2);
// Compute the new ray origin ( _ViewMatrix[0] = right, _ViewMatrix[1] = up, _ViewMatrix[2] = forward )
cameraPosWS += _ViewMatrix[0].xyz * uv.x + _ViewMatrix[1].xyz * uv.y;
// Compute the focus point by intersecting the pinhole ray with the focus plane
float focusDistance = _PathTracedDoFConstants.y;
float t = focusDistance / dot(directionWS, _ViewMatrix[2].xyz);
float3 focusPointWS = GetPrimaryCameraPosition() - t * directionWS;
// The new ray direction should pass through the focus point
directionWS = normalize(focusPointWS - cameraPosWS);
}
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = cameraPosWS;
rayDescriptor.Direction = directionWS;
rayDescriptor.TMin = _RaytracingCameraNearPlane;
rayDescriptor.TMax = FLT_INF;
// Create and init the PathIntersection structure for this
PathIntersection pathIntersection;
pathIntersection.value = 1.0;
pathIntersection.alpha = 1.0;
pathIntersection.remainingDepth = _RaytracingMaxRecursion;
pathIntersection.pixelCoord = currentPixelCoord;
pathIntersection.maxRoughness = 0.0;
// In order to achieve filtering for the textures, we need to compute the spread angle of the pixel
pathIntersection.cone.spreadAngle = _RaytracingPixelSpreadAngle;
pathIntersection.cone.width = 0.0;
// Evaluate the ray intersection
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_PATH_TRACING, 0, 1, 0, rayDescriptor, pathIntersection);
_FrameTexture[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(pathIntersection.value, pathIntersection.alpha);
}
// This should never be called, return magenta just in case
[shader("closesthit")]
void ClosestHit(inout PathIntersection pathIntersection : SV_RayPayload, AttributeData attributeData : SV_IntersectionAttributes)
{
pathIntersection.value = float3(1.0, 0.0, 0.5);
}