// We need only need one bounce given that we want to see the objects and then direct lighting is not done using raytracing #pragma max_recursion_depth 1 // Given that the algorithm requires BSDF evaluation, we need to define this macro #define HAS_LIGHTLOOP // 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 // Include and define the shader pass #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl" #define SHADERPASS SHADERPASS_RAYTRACING_INDIRECT // HDRP include #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/Packing.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.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.core/ShaderLibrary/Sampling/Sampling.hlsl" // Lighting 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/ShaderVariablesRaytracingLightLoop.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.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" // Raytracing includes #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Deferred/RaytracingIntersectonGBuffer.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/RayTracingCommon.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/Common/AtmosphericScatteringRayTracing.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/RayCountManager.cs.hlsl" // The target acceleration structure that we will evaluate the reflexion in TEXTURE2D_X(_DepthTexture); // Texture that holds the raytracing data TEXTURE2D_X(_RaytracingDirectionBuffer); RW_TEXTURE2D_X(float, _RaytracingDistanceBuffer); // Output textures RW_TEXTURE2D_X(float4, _GBufferTexture0RW); RW_TEXTURE2D_X(float4, _GBufferTexture1RW); RW_TEXTURE2D_X(float4, _GBufferTexture2RW); RW_TEXTURE2D_X(float4, _GBufferTexture3RW); // Bake lighting and/or emissive int _RaytracingHalfResolution; uint _RayTracingLayerMask; int _RayCountType; uint _RayBinViewOffset; uint _RayBinTileViewOffset; [shader("miss")] void MissShaderGBuffer(inout RayIntersectionGBuffer rayIntersection : SV_RayPayload) { rayIntersection.t = RAY_TRACING_DISTANCE_FLAG_SKY; } void TraceGBuffer(uint2 currentPixelCoord) { // Read the depth value float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentPixelCoord).x; // Read the direction float4 direction = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentPixelCoord); // 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 || direction.w <= 0.0) { if (direction.w < 0.0) { _RaytracingDistanceBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = _RaytracingRayMaxLength; _GBufferTexture0RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(0.0, 0.0, 0.0, 0.0); _GBufferTexture1RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(0.0, 0.0, 0.0, 0.0); _GBufferTexture2RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(0.0, 0.0, 0.0, 0.0); _GBufferTexture3RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(0.0, 0.0, 0.0, 0.0); } return; } // Compute the position input structure PositionInputs posInput = GetPositionInput(currentPixelCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0); // Decode the world space normal NormalData normalData; DecodeFromNormalBuffer(currentPixelCoord, normalData); // Keep track of the new ray in the counters if (_RayCountEnabled > 0) { uint3 counterIdx = uint3(currentPixelCoord, INDEX_TEXTURE2D_ARRAY_X(_RayCountType)); _RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1; } // Evaluate the ray bias float rayBias = EvaluateRayTracingBias(posInput.positionWS); // Create the ray descriptor for this pixel RayDesc rayDescriptor; rayDescriptor.Origin = posInput.positionWS + normalData.normalWS * rayBias; rayDescriptor.Direction = direction.xyz; rayDescriptor.TMin = 0.0; rayDescriptor.TMax = _RaytracingRayMaxLength; // Adjust world-space position to match the RAS setup with XR single-pass and camera relative ApplyCameraRelativeXR(rayDescriptor.Origin); // Create and init the RayIntersection structure for this RayIntersectionGBuffer rayIntersection; rayIntersection.t = -1.0; rayIntersection.gbuffer0 = float4(0.0, 0.0, 0.0, 0.0); rayIntersection.gbuffer1 = float4(0.0, 0.0, 0.0, 0.0); rayIntersection.gbuffer2 = float4(0.0, 0.0, 0.0, 0.0); rayIntersection.gbuffer3 = float4(0.0, 0.0, 0.0, 0.0); // Evaluate the ray visibility term and PDF TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, _RayTracingLayerMask, 0, 1, 0, rayDescriptor, rayIntersection); // Output the gbuffer _GBufferTexture0RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(LinearToSRGB(rayIntersection.gbuffer0.xyz), rayIntersection.gbuffer0.w); _GBufferTexture1RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer1); _GBufferTexture2RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer2); _GBufferTexture3RW[COORD_TEXTURE2D_X(currentPixelCoord)] = float4(rayIntersection.gbuffer3); _RaytracingDistanceBuffer[COORD_TEXTURE2D_X(currentPixelCoord)] = rayIntersection.t; } [shader("raygeneration")] void RayGenGBuffer() { // 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); // For the half res coordinates, we need to adjust the positions if (_RaytracingHalfResolution) currentPixelCoord = ComputeSourceCoordinates(currentPixelCoord, _RayTracingCheckerIndex); // Trace and output the gbuffer TraceGBuffer(currentPixelCoord); } StructuredBuffer _RayBinResult; StructuredBuffer _RayBinSizeResult; uint _RayBinTileCountX; uint _BufferSizeX; #define RAY_BINNING_TILE_SIZE 16 [shader("raygeneration")] void RayGenGBufferBinned() { // Grab the dimensions of the current raytrace shader uint3 LaunchIndex = DispatchRaysIndex(); UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z); // Pixel coordinate of the current pixel uint2 currentBinIndex = uint2(LaunchIndex.x % _BufferSizeX, LaunchIndex.x / _BufferSizeX); // Compute the various local/tile coordinates uint2 localTileCoordinate = uint2(currentBinIndex.x % RAY_BINNING_TILE_SIZE, currentBinIndex.y % RAY_BINNING_TILE_SIZE); uint localTileIndex = localTileCoordinate.y * RAY_BINNING_TILE_SIZE + localTileCoordinate.x; uint2 tileCoordinate = uint2(currentBinIndex.x / RAY_BINNING_TILE_SIZE, currentBinIndex.y / RAY_BINNING_TILE_SIZE); uint tileIndex = tileCoordinate.y * _RayBinTileCountX + tileCoordinate.x; // Read and unpack the coordiante to screen space coordinates uint globalBinIndex = tileIndex * RAY_BINNING_TILE_SIZE * RAY_BINNING_TILE_SIZE + localTileIndex; uint packedPixelCoordinate = _RayBinResult[globalBinIndex + _RayBinViewOffset * LaunchIndex.z]; uint2 currentPixelCoord = uint2((packedPixelCoordinate & 0xffff0000) >> 16, packedPixelCoordinate & 0xffff); // If the local index of this pixel is beyond the valid count, no need to compute it if (localTileIndex > _RayBinSizeResult[tileIndex + _RayBinTileViewOffset * LaunchIndex.z]) return; // For the half res coordinates, we need to adjust the positions if (_RaytracingHalfResolution) currentPixelCoord = ComputeSourceCoordinates(currentPixelCoord * 0.5, _RayTracingCheckerIndex); // Trace and output the gbuffer TraceGBuffer(currentPixelCoord); }