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