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.
326 lines
15 KiB
326 lines
15 KiB
// 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 31
|
|
|
|
#define HAS_LIGHTLOOP
|
|
|
|
// Include and define the shader pass
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
|
|
#define SHADERPASS SHADERPASS_RAYTRACING
|
|
|
|
// HDRP include
|
|
#define SHADER_TARGET 50
|
|
#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/NormalBuffer.hlsl"
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/BSDF.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/PreIntegratedFGD/PreIntegratedFGD.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonLighting.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightEvaluation.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialEvaluation.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesGlobal.hlsl"
|
|
|
|
// Raytracing 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/RayTracingLightCluster.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/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/Lighting/ScreenSpaceLighting/ScreenSpaceLighting.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"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/RayTracingFallbackHierarchy.cs.hlsl"
|
|
|
|
// The target acceleration structure that we will evaluate the reflexion in
|
|
TEXTURE2D_X(_DepthTexture);
|
|
TEXTURE2D_X(_SsrClearCoatMaskTexture);
|
|
|
|
// Flag value that defines if a given pixel recieves reflections or not
|
|
TYPED_TEXTURE2D_X(uint2, _StencilTexture);
|
|
int _SsrStencilBit;
|
|
|
|
// Output structure of the reflection raytrace shader
|
|
RW_TEXTURE2D_X(float4, _RayTracingLightingTextureRW);
|
|
RW_TEXTURE2D_X(float, _RayTracingDistanceTextureRW);
|
|
|
|
[shader("miss")]
|
|
void MissShaderReflections(inout RayIntersection rayIntersection : SV_RayPayload)
|
|
{
|
|
float3 rayOrigin = WorldRayOrigin();
|
|
float3 rayDirection = WorldRayDirection();
|
|
|
|
float weight = 0.0f;
|
|
|
|
if (RAYTRACINGFALLBACKHIERACHY_REFLECTION_PROBES & _RayTracingRayMissFallbackHierarchy)
|
|
rayIntersection.color = RayTraceReflectionProbes(rayOrigin, rayDirection, weight);
|
|
|
|
if((RAYTRACINGFALLBACKHIERACHY_SKY & _RayTracingRayMissFallbackHierarchy) && weight < 1.0)
|
|
{
|
|
rayIntersection.color += SAMPLE_TEXTURECUBE_ARRAY_LOD(_SkyTexture, s_trilinear_clamp_sampler, rayDirection, 0.0, 0).xyz * (1.0 - weight);
|
|
weight = 1.0f;
|
|
}
|
|
|
|
if (weight > 0.0)
|
|
ApplyFogAttenuation(rayOrigin, rayDirection, rayIntersection.color);
|
|
|
|
rayIntersection.t = _RaytracingRayMaxLength;
|
|
}
|
|
|
|
// Function that evaluates the normal data for a given pixel
|
|
NormalData EvaluateNormalData(uint2 sourceCoord)
|
|
{
|
|
// Decode the world space normal
|
|
NormalData normalData;
|
|
DecodeFromNormalBuffer(sourceCoord, normalData);
|
|
|
|
// Override the roughness by the clearcoat value of this is a clear coat
|
|
float4 coatMask = LOAD_TEXTURE2D_X(_SsrClearCoatMaskTexture, sourceCoord);
|
|
normalData.perceptualRoughness = HasClearCoatMask(coatMask) ? CLEAR_COAT_SSR_PERCEPTUAL_ROUGHNESS : normalData.perceptualRoughness;
|
|
return normalData;
|
|
}
|
|
|
|
[shader("raygeneration")]
|
|
void RayGenIntegration()
|
|
{
|
|
// Grab the dimensions of the current dispatch
|
|
uint3 LaunchIndex = DispatchRaysIndex();
|
|
uint3 LaunchDim = DispatchRaysDimensions();
|
|
|
|
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
|
|
|
|
// Compute the pixel coordinate to evaluate
|
|
uint2 currentCoord = uint2(LaunchIndex.x, LaunchDim.y - LaunchIndex.y - 1);
|
|
|
|
// Clear the output color texture
|
|
_RayTracingLightingTextureRW[COORD_TEXTURE2D_X(currentCoord)] = float4(0.0, 0.0, 0.0, 0.0);
|
|
_RayTracingDistanceTextureRW[COORD_TEXTURE2D_X(currentCoord)] = 0.0;
|
|
|
|
// Read the depth value
|
|
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord).r;
|
|
|
|
// This point is part of the background, we don't really care
|
|
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
|
|
return;
|
|
|
|
// Does this pixel have SSS?
|
|
uint stencilValue = GetStencilValue(LOAD_TEXTURE2D_X(_StencilTexture, currentCoord));
|
|
if ((stencilValue & _SsrStencilBit) == 0)
|
|
return;
|
|
|
|
// Convert this to a world space position
|
|
PositionInputs posInput = GetPositionInput(currentCoord, 1.0/LaunchDim.xy, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
|
|
float distanceToCamera = length(posInput.positionWS);
|
|
// Compute the incident vector on the surfaces
|
|
const float3 viewWS = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
|
|
|
|
// Decode the world space normal
|
|
NormalData normalData = EvaluateNormalData(currentCoord);
|
|
|
|
// Create the local ortho basis
|
|
float3x3 localToWorld = GetLocalFrame(normalData.normalWS);
|
|
|
|
// If this value is beyond the smothness that we allow, no need to compute it
|
|
float perceptualSmoothness = PerceptualRoughnessToPerceptualSmoothness(normalData.perceptualRoughness);
|
|
if (_RaytracingReflectionMinSmoothness > perceptualSmoothness)
|
|
return;
|
|
|
|
// Evaluate the ray bias
|
|
float rayBias = EvaluateRayTracingBias(posInput.positionWS);
|
|
|
|
// Compute the actual roughness
|
|
float roughness = PerceptualRoughnessToRoughness(normalData.perceptualRoughness);
|
|
|
|
// If we only have one bounce, we don't need more than one ray to evaluate the exact signal. However, if we are going for multiple bounces, we may need more, so we cannot clamp the sample count to 1.
|
|
int realSampleCount = _RaytracingMaxRecursion == 1 ? (normalData.perceptualRoughness < 0.01 ? 1 : _RaytracingNumSamples) : _RaytracingNumSamples;
|
|
|
|
// Variable that accumulate the radiance
|
|
float3 finalColor = float3(0.0, 0.0, 0.0);
|
|
float averageDistance = 0.0;
|
|
|
|
// Loop through the samples and add their contribution
|
|
for (int sampleIndex = 0; sampleIndex < realSampleCount; ++sampleIndex)
|
|
{
|
|
// Compute the current sample index
|
|
int globalSampleIndex = _RayTracingReflectionFrameIndex * realSampleCount + sampleIndex;
|
|
|
|
// Generate the new sample (follwing values of the sequence)
|
|
float2 theSample;
|
|
theSample.x = GetBNDSequenceSample(currentCoord, globalSampleIndex, 0);
|
|
theSample.y = GetBNDSequenceSample(currentCoord, globalSampleIndex, 1);
|
|
|
|
// Importance sample the direction using GGX
|
|
float3 sampleDir = float3(0.0, 0.0, 0.0);
|
|
float NdotL, NdotH, VdotH;
|
|
SampleGGXDir(theSample, viewWS, localToWorld, roughness, sampleDir, NdotL, NdotH, VdotH);
|
|
|
|
// If the sample is under the surface
|
|
if (dot(sampleDir, normalData.normalWS) <= 0.0)
|
|
continue;
|
|
|
|
// Make sure the new ray is taken into account in the ray counters
|
|
if (_RayCountEnabled > 0)
|
|
{
|
|
uint3 counterIdx = uint3(currentCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_REFLECTION_FORWARD));
|
|
_RayCountTexture[counterIdx] = _RayCountTexture[counterIdx] + 1;
|
|
}
|
|
|
|
// Create the ray descriptor for this pixel
|
|
RayDesc rayDescriptor;
|
|
rayDescriptor.Origin = posInput.positionWS + normalData.normalWS * rayBias;
|
|
rayDescriptor.Direction = sampleDir;
|
|
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
|
|
RayIntersection rayIntersection;
|
|
rayIntersection.color = float3(0.0, 0.0, 0.0);
|
|
rayIntersection.t = -1.0;
|
|
rayIntersection.remainingDepth = 1;
|
|
rayIntersection.sampleIndex = globalSampleIndex;
|
|
rayIntersection.pixelCoord = currentCoord;
|
|
|
|
// In order to achieve filtering for the textures, we need to compute the spread angle of the pixel
|
|
rayIntersection.cone.spreadAngle = _RaytracingPixelSpreadAngle + roughnessToSpreadAngle(roughness);
|
|
rayIntersection.cone.width = distanceToCamera * _RaytracingPixelSpreadAngle;
|
|
|
|
// Evaluate the ray intersection
|
|
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_REFLECTION, 0, 1, 0, rayDescriptor, rayIntersection);
|
|
|
|
// The clamping process is different for the sky and rest
|
|
float3 sampleColor = 0.0;
|
|
if (rayIntersection.t == _RaytracingRayMaxLength)
|
|
{
|
|
// Convert to HSV space
|
|
sampleColor = RgbToHsv(rayIntersection.color * GetCurrentExposureMultiplier());
|
|
|
|
// Expose and clamp the final color
|
|
sampleColor.z = clamp(sampleColor.z, 0.0, _RaytracingIntensityClamp);
|
|
|
|
// Convert back to HSV space
|
|
sampleColor = HsvToRgb(sampleColor) * GetInverseCurrentExposureMultiplier();
|
|
}
|
|
else
|
|
{
|
|
// Expose and clamp the final color
|
|
sampleColor = clamp(rayIntersection.color * GetCurrentExposureMultiplier(), 0.0, _RaytracingIntensityClamp) * GetInverseCurrentExposureMultiplier();
|
|
}
|
|
|
|
// Contribute to the pixel
|
|
finalColor += sampleColor;
|
|
averageDistance += rayIntersection.t;
|
|
}
|
|
|
|
// Normalize the value
|
|
if (realSampleCount != 0.0)
|
|
{
|
|
float normalizationFactor = 1.0 / realSampleCount;
|
|
finalColor *= normalizationFactor;
|
|
averageDistance *= normalizationFactor;
|
|
}
|
|
|
|
// We also need to compute the fade factor for this sample
|
|
float weightValue = _RaytracingReflectionSmoothnessFadeStart == _RaytracingReflectionMinSmoothness ? 1.0 : saturate((perceptualSmoothness - _RaytracingReflectionMinSmoothness) / (_RaytracingReflectionSmoothnessFadeStart -_RaytracingReflectionMinSmoothness));
|
|
|
|
// We store the sampled color and the weight that shall be used for it (1.0)
|
|
_RayTracingLightingTextureRW[COORD_TEXTURE2D_X(currentCoord)] = float4(finalColor, weightValue);
|
|
_RayTracingDistanceTextureRW[COORD_TEXTURE2D_X(currentCoord)] = averageDistance;
|
|
}
|
|
|
|
[shader("raygeneration")]
|
|
void RayGenIntegrationTransparent()
|
|
{
|
|
// Grab the dimensions of the current dispatch
|
|
uint3 LaunchIndex = DispatchRaysIndex();
|
|
uint3 LaunchDim = DispatchRaysDimensions();
|
|
|
|
UNITY_XR_ASSIGN_VIEW_INDEX(LaunchIndex.z);
|
|
|
|
// Compute the pixel coordinate to evaluate
|
|
uint2 currentCoord = uint2(LaunchIndex.x, LaunchDim.y - LaunchIndex.y - 1);
|
|
|
|
// Clear the output color texture
|
|
_RayTracingLightingTextureRW[COORD_TEXTURE2D_X(currentCoord)] = float4(0.0, 0.0, 0.0, 0.0);
|
|
|
|
// Read the depth value
|
|
float depthValue = LOAD_TEXTURE2D_X(_DepthTexture, currentCoord).r;
|
|
|
|
// This point is part of the background, we don't really care
|
|
if (depthValue == UNITY_RAW_FAR_CLIP_VALUE)
|
|
return;
|
|
|
|
// Does this pixel have SSS?
|
|
uint stencilValue = GetStencilValue(LOAD_TEXTURE2D_X(_StencilTexture, currentCoord));
|
|
if ((stencilValue & _SsrStencilBit) == 0)
|
|
return;
|
|
|
|
// Convert this to a world space position
|
|
PositionInputs posInput = GetPositionInput(currentCoord, 1.0/LaunchDim.xy, depthValue, UNITY_MATRIX_I_VP, GetWorldToViewMatrix(), 0);
|
|
float distanceToCamera = length(posInput.positionWS);
|
|
|
|
float3 positionWS = posInput.positionWS;
|
|
|
|
// Compute the incident vector on the surfaces
|
|
const float3 viewWS = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
|
|
|
|
// Decode the world space normal
|
|
NormalData normalData;
|
|
DecodeFromNormalBuffer(currentCoord, normalData);
|
|
|
|
// If this value is beyond the smothness that we allow, no need to compute it
|
|
float perceptualSmoothness = PerceptualRoughnessToPerceptualSmoothness(normalData.perceptualRoughness);
|
|
if (_RaytracingReflectionMinSmoothness > perceptualSmoothness)
|
|
return;
|
|
|
|
// Compute the reflected direction
|
|
float3 reflectionDir = reflect(-viewWS, normalData.normalWS);
|
|
|
|
// Make sure the new ray is taken into account in the ray counters
|
|
if (_RayCountEnabled > 0)
|
|
{
|
|
uint3 counterIdx = uint3(currentCoord, INDEX_TEXTURE2D_ARRAY_X(RAYCOUNTVALUES_REFLECTION_FORWARD));
|
|
_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 = positionWS + normalData.normalWS * rayBias;
|
|
rayDescriptor.Direction = reflectionDir;
|
|
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
|
|
RayIntersection rayIntersection;
|
|
rayIntersection.color = float3(0.0, 0.0, 0.0);
|
|
rayIntersection.t = -1.0;
|
|
rayIntersection.remainingDepth = 1;
|
|
rayIntersection.sampleIndex = 0;
|
|
rayIntersection.pixelCoord = currentCoord;
|
|
|
|
// In order to achieve filtering for the textures, we need to compute the spread angle of the pixel
|
|
rayIntersection.cone.spreadAngle = _RaytracingPixelSpreadAngle;
|
|
rayIntersection.cone.width = distanceToCamera * _RaytracingPixelSpreadAngle;
|
|
|
|
// Evaluate the ray intersection
|
|
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_REFLECTION, 0, 1, 0, rayDescriptor, rayIntersection);
|
|
|
|
// We store the sampled color and the weight that shall be used for it (1.0)
|
|
_RayTracingLightingTextureRW[COORD_TEXTURE2D_X(currentCoord)] = float4(rayIntersection.color, 1.0);
|
|
_RayTracingDistanceTextureRW[COORD_TEXTURE2D_X(currentCoord)] = rayIntersection.t;
|
|
}
|