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.
 
 
 
 

341 lines
16 KiB

#pragma kernel RaytracingDeferred RAYTRACING_DEFERRED=RaytracingDeferred
#pragma kernel RaytracingDeferredHalf RAYTRACING_DEFERRED=RaytracingDeferredHalf HALF_RESOLUTION
#pragma kernel RaytracingDiffuseDeferred
// Given that the algorithm requires BSDF evaluation, we need to define this macro
#define HAS_LIGHTLOOP
// Environment data that need to be used, is from WorldLights
#define WORLD_ENVIRONMENT_DATA
// If you need to change this, be sure to read this comment.
// For raytracing we decided to force the shadow quality to low.
// - The performance is the first reason, given that it may happen during the ray tracing stage for indirect or in a non-tiled context for deferred
// we want to save that cost as it may increase signfiicantly the cost..
// - The second reason is that some filtering modes require the screen space position (at the moment you read this comment high and ultra high), which we cannot provide
// in a ray tracing context.
// In addition to that, we intentionally disabled dithering for the ray tracing case as it requires the screen space position.
#define SHADOW_LOW
#pragma only_renderers d3d11 xboxseries ps5
// Needed for the ray miss and the last bounce indirect diffuse lighting
#pragma multi_compile _ PROBE_VOLUMES_L1 PROBE_VOLUMES_L2
// 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 generic includes
#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/ShaderLibrary/ShaderVariables.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"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitRayTracing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/BuiltinGIUtilities.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.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/ShaderVariablesRaytracingLightLoop.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingLightLoop.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/RenderPipeline/Raytracing/RayTracingFallbackHierarchy.cs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RayTracingCommon.hlsl"
#define RAYTRACING_DEFERRED_TILE_SIZE 8
TEXTURE2D_X(_DepthTexture);
TEXTURE2D_X(_RaytracingDirectionBuffer);
TEXTURE2D_X(_RaytracingDistanceBuffer);
RW_TEXTURE2D_X(float4, _RaytracingLitBufferRW);
RW_TEXTURE2D_X(float, _RaytracingDistanceBufferRW);
[numthreads(RAYTRACING_DEFERRED_TILE_SIZE, RAYTRACING_DEFERRED_TILE_SIZE, 1)]
void RAYTRACING_DEFERRED(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
// Compute the pixel position to process
uint2 currentCoord = groupId * RAYTRACING_DEFERRED_TILE_SIZE + groupThreadId;
// Initialize the output buffer
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)] = float4(0.0, 0.0, 0.0, 0.0);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentCoord)] = 0.0;
#ifdef HALF_RESOLUTION
currentCoord = ComputeSourceCoordinates(currentCoord, _RayTracingCheckerIndex);
#endif
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord).x;
// If this is a background pixel or an invalid ray, leave right away
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE || LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentCoord).w < 0.0f)
return;
// First let's compute the position of the pixel from which the ray has been shot
PositionInputs sourcePosInput = GetPositionInput(currentCoord, _ScreenSize.zw, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
// Fetch the intersection distance of the ray
float rayDistance = LOAD_TEXTURE2D_X(_RaytracingDistanceBuffer, currentCoord).x;
// Fetch the direction of the ray
float3 rayDirection = LOAD_TEXTURE2D_X(_RaytracingDirectionBuffer, currentCoord).xyz;
// if the distance is exactly zero, this means we are facing an environement ray that we need to evaluate
float3 finalColor = 0.0f;
bool rayIsSky = false;
if (RayTracingGBufferIsSky(rayDistance))
{
// Weight value used to do the blending
float weight = 0.0;
rayIsSky = true;
// Read the pixel normal
NormalData normalData;
DecodeFromNormalBuffer(currentCoord.xy, normalData);
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
// Try the APV if enabled
if(_EnableProbeVolumes && _RayTracingAPVRayMiss)
{
BuiltinData apvBuiltinData;
ZERO_INITIALIZE(BuiltinData, apvBuiltinData);
// Read from the APV
EvaluateAdaptiveProbeVolume(GetAbsolutePositionWS(sourcePosInput.positionWS),
normalData.normalWS, -normalData.normalWS,
GetWorldSpaceNormalizeViewDir(sourcePosInput.positionWS),
sourcePosInput.positionSS,
_RaytracingAPVLayerMask,
apvBuiltinData.bakeDiffuseLighting,
apvBuiltinData.backBakeDiffuseLighting); // Not used
// Propagate the value to the final color and set the weight to 1.0
finalColor = apvBuiltinData.bakeDiffuseLighting;
weight = 1.0;
}
#endif
if ((RAYTRACINGFALLBACKHIERACHY_REFLECTION_PROBES & _RayTracingRayMissFallbackHierarchy) && weight < 1.0f)
finalColor += RayTraceReflectionProbes(sourcePosInput.positionWS, rayDirection, weight);
if((RAYTRACINGFALLBACKHIERACHY_SKY & _RayTracingRayMissFallbackHierarchy) && weight == 0.0f)
{
if(_RayTracingRayMissUseAmbientProbeAsSky)
finalColor = EvaluateAmbientProbe(normalData.normalWS) * (1.0 - weight);
else
finalColor = SAMPLE_TEXTURECUBE_ARRAY_LOD(_SkyTexture, s_trilinear_clamp_sampler, rayDirection, 0.0, 0).xyz * (1.0 - weight);
weight = 1.0;
}
if (weight > 0.0)
{
// Apply the fog attenuation
ApplyFogAttenuation(sourcePosInput.positionWS, rayDirection, finalColor);
// Apply the exposure
finalColor *= GetCurrentExposureMultiplier();
// Only clamp if required
if (_RayTracingClampingFlag)
{
// In the case of the sky we always want to operate the clamping in hsv space (reflections and indirect diffuse)
finalColor = RayTracingHSVClamp(finalColor, _RaytracingIntensityClamp);
}
}
}
else if (RayTracingGBufferIsUnlit(rayDistance))
{
finalColor = LOAD_TEXTURE2D_X(_GBufferTexture3, currentCoord).rgb;
// Only clamp if required
if (_RayTracingClampingFlag)
{
// Expose, clamp and inverse exposure. Though depending on the signal nature we go for different clamping strategies
if (_RaytracingPreExposition)
{
// Clamp in HSV space
finalColor = RayTracingHSVClamp(finalColor, _RaytracingIntensityClamp);
}
else
{
finalColor = clamp(finalColor, 0.0, _RaytracingIntensityClamp);
}
}
// For unlit material, the distance is stored negatively so we need to apply an abs to it.
rayDistance = abs(rayDistance);
}
// If the distance is negative, this means it is a sky pixel or an unlit material
if (!RayTracingGBufferIsLit(rayDistance))
{
#if defined(HALF_RESOLUTION)
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord / 2)] = float4(finalColor * (_RaytracingPreExposition ? 1.0 : GetInverseCurrentExposureMultiplier()), 0.0);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentCoord / 2)] = rayIsSky ? _RaytracingRayMaxLength : rayDistance;
#else
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)] = float4(finalColor * (_RaytracingPreExposition ? 1.0 : GetInverseCurrentExposureMultiplier()), 0.0);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentCoord)] = rayIsSky ? _RaytracingRayMaxLength : rayDistance;
#endif
return;
}
// Then compute the pos input of the intersection vertice
float3 intersectionPositionWS = sourcePosInput.positionWS + rayDirection * rayDistance;
PositionInputs posInput = GetPositionInput(currentCoord, _ScreenSize.zw, intersectionPositionWS);
// Read the bsdf data and builtin data from the gbuffer
BSDFData bsdfData;
ZERO_INITIALIZE(BSDFData, bsdfData);
BuiltinData builtinData;
ZERO_INITIALIZE(BuiltinData, builtinData);
uint featureFlags = UINT_MAX;
DecodeFromGBuffer(currentCoord, featureFlags, bsdfData, builtinData);
builtinData.renderingLayers = RENDERING_LAYERS_MASK;
builtinData.shadowMask0 = 1.0;
builtinData.shadowMask1 = 1.0;
builtinData.shadowMask2 = 1.0;
builtinData.shadowMask3 = 1.0;
PreLightData preLightData = GetPreLightData(-rayDirection, posInput, bsdfData);
// Fill the ray context
RayContext rayContext;
rayContext.reflection = 0.0;
rayContext.reflectionWeight = 0.0;
rayContext.transmission = 0.0;
rayContext.transmissionWeight = 0.0;
rayContext.useAPV = 1;
// Evaluate the complete lighting
LightLoopOutput lightLoopOutput;
LightLoop(-rayDirection, posInput, preLightData, bsdfData, builtinData, rayContext, lightLoopOutput);
// Alias
float3 diffuseLighting = lightLoopOutput.diffuseLighting;
float3 specularLighting = lightLoopOutput.specularLighting;
finalColor = (diffuseLighting + specularLighting);
// Apply fog attenuation
ApplyFogAttenuation(sourcePosInput.positionWS, rayDirection, rayDistance, finalColor, true);
// Only clamp if required
if (_RayTracingClampingFlag)
{
// Expose, clamp and inverse exposure. Though depending on the signal nature we go for different clamping strategies
if (_RaytracingPreExposition)
{
// Clamp in HSV space
finalColor = RayTracingHSVClamp(finalColor * GetCurrentExposureMultiplier(), _RaytracingIntensityClamp);
}
else
{
finalColor = clamp(finalColor * GetCurrentExposureMultiplier(), 0.0, _RaytracingIntensityClamp) * GetInverseCurrentExposureMultiplier();
}
}
#if defined(HALF_RESOLUTION)
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord / 2)] = float4(finalColor, 1.0);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentCoord / 2)] = rayDistance;
#else
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)] = float4(finalColor, 1.0);
_RaytracingDistanceBufferRW[COORD_TEXTURE2D_X(currentCoord)] = rayDistance;
#endif
}
// Input textures for the diffuse deferred lightloop that we will be executing
// Position at the exit point
TEXTURE2D_X(_PositionTextureRW);
// Normal value at the exit point
TEXTURE2D_X(_NormalTextureRW);
// Direction value at the exit point
TEXTURE2D_X(_DirectionTextureRW);
// Diffuse lighting at the exit point
TEXTURE2D_X(_DiffuseLightingTextureRW);
// Through put of the walk that was calculated
TEXTURE2D_X(_ThroughputTextureRW);
[numthreads(RAYTRACING_DEFERRED_TILE_SIZE, RAYTRACING_DEFERRED_TILE_SIZE, 1)]
void RaytracingDiffuseDeferred(uint3 dispatchThreadId : SV_DispatchThreadID, uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z);
// Compute the pixel position to process
uint2 currentCoord = groupId * RAYTRACING_DEFERRED_TILE_SIZE + groupThreadId;
// Read the depth value
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord).x;
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
return;
// Read the throughput
float3 throughput = LOAD_TEXTURE2D_X(_ThroughputTextureRW, currentCoord).xyz;
// If the path is black, no need to light this
if (length(throughput) == 0.0)
{
// Simply propagate the previous value
float3 previousValue = _RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)].xyz;
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)] = float4(previousValue, 0.0);
return;
}
// Read the normal
float3 normalWS = LOAD_TEXTURE2D_X(_NormalTextureRW, currentCoord).xyz;
// Create our diffuse white BSDF Data
BSDFData bsdfData;
ZERO_INITIALIZE(BSDFData, bsdfData);
bsdfData.materialFeatures = MATERIALFEATUREFLAGS_LIT_STANDARD;
bsdfData.diffuseColor = float3(1.0, 1.0, 1.0);
bsdfData.fresnel0 = DEFAULT_SPECULAR_VALUE;
bsdfData.ambientOcclusion = 1.0;
bsdfData.perceptualRoughness = 1.0;
bsdfData.specularOcclusion = 1.0;
bsdfData.normalWS = normalWS;
bsdfData.geomNormalWS = normalWS;
ConvertAnisotropyToRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
// Create the built-in data
BuiltinData builtinData;
ZERO_INITIALIZE(BuiltinData, builtinData);
builtinData.bakeDiffuseLighting = LOAD_TEXTURE2D_X(_DiffuseLightingTextureRW, currentCoord).xyz; // This also contain emissive (and * AO if no lightlayers)
builtinData.renderingLayers = RENDERING_LAYERS_MASK;
builtinData.shadowMask0 = 1.0;
builtinData.shadowMask1 = 1.0;
builtinData.shadowMask2 = 1.0;
builtinData.shadowMask3 = 1.0;
// We are evaluating a diffuse signal so view does not matter, let's pick the one that is guaranteed to be right (for some reason the LTC code fails if V == N)
float3 viewWS = LOAD_TEXTURE2D_X(_DirectionTextureRW, currentCoord).xyz;
float3 intersectionPositionWS = LOAD_TEXTURE2D_X(_PositionTextureRW, currentCoord).xyz;
// Create the pos input
PositionInputs posInput = GetPositionInput(currentCoord, _ScreenSize.zw, intersectionPositionWS);
// Compute the prelight data
PreLightData preLightData = GetPreLightData(viewWS, posInput, bsdfData);
// Fill the ray context
RayContext rayContext;
rayContext.reflection = 0.0;
rayContext.reflectionWeight = 0.0;
rayContext.transmission = 0.0;
rayContext.transmissionWeight = 0.0;
rayContext.useAPV = 1;
// Evaluate lighting
LightLoopOutput lightLoopOutput;
LightLoop(viewWS, posInput, preLightData, bsdfData, builtinData, rayContext, lightLoopOutput);
// Alias
float3 diffuseLighting = lightLoopOutput.diffuseLighting;
float3 specularLighting = lightLoopOutput.specularLighting;
// Read the previous value and combine with the current lighting
float3 previousValue = _RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)].xyz;
_RaytracingLitBufferRW[COORD_TEXTURE2D_X(currentCoord)] = float4(previousValue + throughput * diffuseLighting, 1.0);
}