// 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; }