You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

550 lines
25 KiB

// We need only need one bounce given that we want to see the if there is anything that occludes the area light
#pragma max_recursion_depth 1
// Macro that defines if we are raytracing from the light source to the object in backface culling or the opposite in frontface culling
#define LIGHT_TO_SURFACE
// Given that the algorithm requires BSDF evaluation, we need to define this macro
#define HAS_LIGHTLOOP
// Given that the algorithm requires BSDF evaluation, we need to define this macro
#define SKIP_RASTERIZED_AREA_SHADOWS
// Given that this pass does not use the shadow algorithm multi-compile, we need to define SHADOW_LOW to quite the shadow algorithm error
#define SHADOW_LOW
// Required for contact shadows
#define USE_FPTL_LIGHTLIST
// We are using DX12 here
#define SHADER_TARGET 50
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
#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.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#define SHADERPASS SHADERPASS_RAYTRACING
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesFunctions.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/ContactShadows.hlsl"
// Raytracing includes
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingIntersection.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingSampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Common/RayTracingHelpers.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RaytracingMIS.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/RayCountManager.cs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/RayTracingShadowUtilities.hlsl"
// Light Data
uint _RaytracingTargetAreaLight;
// The target acceleration structure that we will evaluate the reflexion in
TEXTURE2D_X(_DepthTexture);
// Output structure of the shadows raytrace shader
TEXTURE2D_X(_RaytracedAreaShadowSample);
TEXTURE2D_X(_AnalyticProbBuffer);
RW_TEXTURE2D_X(float2, _RaytracedAreaShadowIntegration);
[shader("miss")]
void MissShaderShadows(inout RayIntersectionVisibility rayIntersection : SV_RayPayload)
{
rayIntersection.color = float3(1.0, 1.0, 1.0);
}
[shader("miss")]
void MissShaderShadowsColor(inout RayIntersectionVisibility rayIntersection : SV_RayPayload)
{
// Does nothing intentionally
}
// Texture that holds the raytracing data
TEXTURE2D_X(_RaytracingDirectionBuffer);
TEXTURE2D_X(_RayTracingLengthBuffer);
[shader("raygeneration")]
void RayGenAreaShadowSingle()
{
// Grab the dimensions of the current raytrace shader
uint3 LaunchIndex = DispatchRaysIndex();
uint3 LaunchDim = DispatchRaysDimensions();
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
// Pixel coordinate of the current pixel
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Read the previous value of the buffer
float2 previousValue = _RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)];
float2 currentSample = LOAD_TEXTURE2D_X(_RaytracedAreaShadowSample, currentPixelCoord).xy;
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x;
// If this is the background, or UnL is null or this pixel has been flagged as invalid, no
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || currentSample.y == 0.0 || LOAD_TEXTURE2D_X(_AnalyticProbBuffer, currentPixelCoord).y < 0.0)
{
_RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(previousValue.x, previousValue.y);
return;
}
// Make sure it is taken into account in the ray counters
if (_RayCountEnabled > 0)
{
uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_AREA_LIGHT));
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
}
// Fetch the data of the area light
LightData lightData = _LightDatas[_RaytracingTargetAreaLight];
// Compute the position input structure
PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Evaluate the ray bias
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
// Decode the world space normal
NormalData normalData;
DecodeFromNormalBuffer(currentPixelCoord, normalData);
// Read the ray distance
float3 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord).xyz;
float rayDistance = LOAD_TEXTURE2D_X(_RayTracingLengthBuffer, currentPixelCoord).x;
float3 rayOrigin = posInput.positionWS + rayDirection * rayDistance - lightData.forward * rayBias;
float3 rayDestination = posInput.positionWS + normalData.normalWS * rayBias;
rayDistance = length(rayDestination - rayOrigin);
rayDirection = (rayDestination - rayOrigin) / rayDistance;
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = rayDistance;
// Adjust world-space position to match the RAS setup with XR single-pass and camera relative
ApplyCameraRelativeXR(rayDescriptor.Origin);
// Create and init the RayIntersectionVisibility structure for this
RayIntersectionVisibility rayIntersection;
rayIntersection.color = float3(0.0, 0.0, 0.0);
// Evaluate the ray visibility term and PDF
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 0, rayDescriptor, rayIntersection);
// Add the contribution of this sample
_RaytracedAreaShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float2(rayIntersection.color.x * currentSample.x + previousValue.x, currentSample.y + previousValue.y);
}
// Given that we do not want to have the blur stop right away when there is no intersection, this value has been been experimentally validated
#define MISS_RAY_TRACING_SHADOW_DISTANCE 5.0f
RW_TEXTURE2D_X(float, _RaytracedShadowIntegration);
RW_TEXTURE2D_X(float, _RaytracingDistanceBufferRW);
RW_TEXTURE2D_X(float, _VelocityBuffer);
float _DirectionalMaxRayLength;
[shader("raygeneration")]
void RayGenDirectionalShadowSingle()
{
// Grab the dimensions of the current raytrace shader
uint3 LaunchIndex = DispatchRaysIndex();
uint3 LaunchDim = DispatchRaysDimensions();
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
// Pixel coordinate of the current pixel
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Read the previous value of the buffer
float previousIntegrationValue = _RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)].x;
float previousVelocityValue = _VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].x;
float previousDistanceValue = _RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)].x;
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x;
// If this is the background pixel, skip.
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
return;
// Make sure it is taken into account in the ray counters
if (_RayCountEnabled > 0)
{
uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_DIRECTIONAL));
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
}
// Compute the position input structure
PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Evaluate the ray bias
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
// Decode the world space normal
NormalData normalData;
DecodeFromNormalBuffer(currentPixelCoord, normalData);
// Read the ray distance
float4 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord);
float3 rayOrigin = posInput.positionWS + normalData.normalWS * rayBias;
// If we are inside the light (spot or point), we consider that we have no occlusion and end the execution.
if (rayDirection.w <= 0.0)
return;
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = _DirectionalMaxRayLength;
// Adjust world-space position to match the RAS setup with XR single-pass and camera relative
ApplyCameraRelativeXR(rayDescriptor.Origin);
// Create and init the RayIntersectionVisibility structure for this
RayIntersectionVisibility rayIntersection;
rayIntersection.color = float3(0.0, 0.0, 0.0);
rayIntersection.velocity = 0.0;
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 0, rayDescriptor, rayIntersection);
// Add the contribution of this sample
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = previousIntegrationValue + rayIntersection.color.x / (float)_RaytracingNumSamples;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = max(rayIntersection.velocity, previousVelocityValue);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)] = previousDistanceValue + rayIntersection.t / (float)_RaytracingNumSamples;
}
RW_TEXTURE2D_X(float4, _RaytracedColorShadowIntegration);
[shader("raygeneration")]
void RayGenDirectionalColorShadowSingle()
{
// Grab the dimensions of the current raytrace shader
uint3 LaunchIndex = DispatchRaysIndex();
uint3 LaunchDim = DispatchRaysDimensions();
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
// Pixel coordinate of the current pixel
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Read the previous value of the buffer
float3 previousIntergrationValue = _RaytracedColorShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)].xyz;
float previousVelocityValue = _VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].x;
float previousDistanceValue = _RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)].x;
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x;
// If this is the background pixel, skip.
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
return;
// Make sure it is taken into account in the ray counters
if (_RayCountEnabled > 0)
{
uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_DIRECTIONAL));
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
}
// Compute the position input structure
PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Evaluate the ray bias
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
// Decode the world space normal
NormalData normalData;
DecodeFromNormalBuffer(currentPixelCoord, normalData);
// Read the ray distance
float4 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord);
float3 rayOrigin = posInput.positionWS + normalData.normalWS * rayBias;
// If we are inside the light (spot or point), we consider that we have no occlusion and end the execution.
if (rayDirection.w <= 0.0)
return;
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = _DirectionalMaxRayLength;
// Adjust world-space position to match the RAS setup with XR single-pass and camera relative
ApplyCameraRelativeXR(rayDescriptor.Origin);
// Create and init the RayIntersectionVisibility structure for this
RayIntersectionVisibility rayIntersection;
rayIntersection.color = float3(0.0, 0.0, 0.0);
rayIntersection.velocity = 0.0;
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, RAYTRACINGRENDERERFLAG_CAST_SHADOW_OPAQUE, 0, 1, 0, rayDescriptor, rayIntersection);
// If we did not hit an opaque object
if (rayIntersection.color.x != 0.0)
{
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = _DirectionalMaxRayLength;
rayIntersection.color = float3(1.0, 1.0, 1.0);
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_CAST_SHADOW_TRANSPARENT, 0, 1, 1, rayDescriptor, rayIntersection);
}
_RaytracedColorShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(previousIntergrationValue + rayIntersection.color / (float)_RaytracingNumSamples, 1.0);
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = max(rayIntersection.velocity, previousVelocityValue);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)] = previousDistanceValue + rayIntersection.t / (float)_RaytracingNumSamples;
}
[shader("raygeneration")]
void RayGenShadowSegmentSingle()
{
// Grab the dimensions of the current raytrace shader
uint3 LaunchIndex = DispatchRaysIndex();
uint3 LaunchDim = DispatchRaysDimensions();
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
// Pixel coordinate of the current pixel
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x;
// If this is the background, we do not need to do anything
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
return;
// Fetch the ray direction
float4 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord);
// If we are:
// - Inside the light (spot or point)
// - An Unlit pixel
// We consider that we have no occlusion and skip the tracing.
if (rayDirection.w == POINT_WHITE_PDF)
{
// Read the previous value and add one
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// If this point is outside of the light range, then we force the result to black (as all rays starting from this ponit will have the same result)
if (rayDirection.w == POINT_BLACK_PDF)
{
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = 0.0;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// Read the previous integration value
float previousValue = _RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)];
// If this direction is going under the surface, generate an occlusion and skip the tracing.
if (rayDirection.w == POINT_BACK_FACE_PDF)
{
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = previousValue;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// Make sure it is taken into account in the ray counters
if (_RayCountEnabled > 0)
{
uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_POINT_SPOT ));
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
}
// Compute the world space position of the source pixel
PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Evaluate the ray bias
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
// Decode the world space normal
NormalData normalData;
DecodeFromNormalBuffer(currentPixelCoord, normalData);
// Read the ray distance
float rayDistance = LOAD_TEXTURE2D_X(_RayTracingLengthBuffer, currentPixelCoord).x;
// Recompute the ray parameters
float3 rayOrigin = posInput.positionWS + normalData.normalWS * rayBias;
float3 rayDestination = rayOrigin + rayDirection.xyz * (rayDistance - rayBias);
// Re-normalize using t
rayDistance = length(rayDestination - rayOrigin);
rayDirection.xyz = (rayDestination - rayOrigin) / rayDistance;
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = rayDistance;
// Adjust world-space position to match the RAS setup with XR single-pass and camera relative
ApplyCameraRelativeXR(rayDescriptor.Origin);
// Create and init the RayIntersectionVisibility structure for this
RayIntersectionVisibility rayIntersection;
rayIntersection.color = float3(0.0, 0.0, 0.0);
rayIntersection.velocity = 0.0;
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term and PDF
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 0, rayDescriptor, rayIntersection);
// Add the contribution of this sample
float previousVelocityValue = _VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].x;
float previousDistanceValue = _RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)].x;
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = previousValue + rayIntersection.color.x / (float)_RaytracingNumSamples;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = max(rayIntersection.velocity, previousVelocityValue);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)] = previousDistanceValue + rayIntersection.t / (float)_RaytracingNumSamples;
}
[shader("raygeneration")]
void RayGenSemiTransparentShadowSegmentSingle()
{
// Grab the dimensions of the current raytrace shader
uint3 LaunchIndex = DispatchRaysIndex();
uint3 LaunchDim = DispatchRaysDimensions();
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
// Pixel coordinate of the current pixel
uint2 currentPixelCoord = uint2(LaunchIndex.x, LaunchIndex.y);
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x;
// If this is the background, we do not need to do anything
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
return;
// Fetch the ray direction
float4 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord);
// If we are:
// - Inside the light (spot or point)
// - An Unlit pixel
// We consider that we have no occlusion and skip the tracing.
if (rayDirection.w == POINT_WHITE_PDF)
{
// Read the previous value and add one
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// If this point is outside of the light range, then we force the result to black (as all rays starting from this ponit will have the same result)
if (rayDirection.w == POINT_BLACK_PDF)
{
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = 0.0;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// Read the previous integration value
float previousValue = _RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)];
// If this direction is going under the surface, generate an occlusion and skip the tracing.
if (rayDirection.w == POINT_BACK_FACE_PDF)
{
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = previousValue;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = 1.0;
return;
}
// Make sure it is taken into account in the ray counters
if (_RayCountEnabled > 0)
{
uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_SHADOW_POINT_SPOT ));
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
}
// Compute the world space position of the source pixel
PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Evaluate the ray bias
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
// Decode the world space normal
NormalData normalData;
DecodeFromNormalBuffer(currentPixelCoord, normalData);
// Read the ray distance
float rayDistance = LOAD_TEXTURE2D_X(_RayTracingLengthBuffer, currentPixelCoord).x;
// Recompute the ray parameters
float3 rayOrigin = posInput.positionWS + normalData.normalWS * rayBias;
float3 rayDestination = rayOrigin + rayDirection.xyz * (rayDistance - rayBias);
// Re-normalize using t
rayDistance = length(rayDestination - rayOrigin);
rayDirection.xyz = (rayDestination - rayOrigin) / rayDistance;
// Create the ray descriptor for this pixel
RayDesc rayDescriptor;
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = rayDistance;
// Adjust world-space position to match the RAS setup with XR single-pass and camera relative
ApplyCameraRelativeXR(rayDescriptor.Origin);
// Create and init the RayIntersectionVisibility structure for this
RayIntersectionVisibility rayIntersection;
rayIntersection.color = float3(0.0, 0.0, 0.0);
rayIntersection.velocity = 0.0;
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term and PDF
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH
, RAYTRACINGRENDERERFLAG_CAST_SHADOW_OPAQUE, 0, 1, 0, rayDescriptor, rayIntersection);
// If we did not hit an opaque object
if (rayIntersection.color.x != 0.0)
{
rayDescriptor.Origin = rayOrigin;
rayDescriptor.Direction = rayDirection.xyz;
rayDescriptor.TMin = 0.0;
rayDescriptor.TMax = rayDistance;
rayIntersection.color = float3(1.0, 1.0, 1.0);
rayIntersection.t = MISS_RAY_TRACING_SHADOW_DISTANCE;
// Evaluate the ray visibility term
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_FRONT_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_CAST_SHADOW_TRANSPARENT, 0, 1, 1, rayDescriptor, rayIntersection);
}
// Add the contribution of this sample
float previousVelocityValue = _VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)].x;
float previousDistanceValue = _RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)].x;
_RaytracedShadowIntegration[COORD_TEXTURE2D_X(currentPixelCoord)] = previousValue + Luminance(rayIntersection.color) / (float)_RaytracingNumSamples;
_VelocityBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = max(rayIntersection.velocity, previousVelocityValue);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentPixelCoord)] = previousDistanceValue + rayIntersection.t / (float)_RaytracingNumSamples;
}