您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
174 行
7.0 KiB
174 行
7.0 KiB
// Each #kernel tells which function to compile; you can have many kernels
|
|
#pragma kernel DeferredDirectionalShadow DEFERRED_DIRECTIONAL=DeferredDirectionalShadow
|
|
#pragma kernel DeferredDirectionalShadow_Contact DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact ENABLE_CONTACT_SHADOWS
|
|
#pragma kernel DeferredContactShadow
|
|
|
|
#ifdef SHADER_API_PSSL
|
|
# pragma argument( scheduler=minpressure ) // instruct the shader compiler to prefer minimizing vgpr usage
|
|
#endif
|
|
|
|
#include "CoreRP/ShaderLibrary/Common.hlsl"
|
|
#include "../ShaderVariables.hlsl"
|
|
#include "../Material/NormalBuffer.hlsl"
|
|
#include "Lighting.hlsl"
|
|
|
|
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
|
|
|
|
//#pragma enable_d3d11_debug_symbols
|
|
|
|
RWTexture2D<float4> _DeferredShadowTextureUAV;
|
|
|
|
CBUFFER_START(DeferredShadowParameters)
|
|
uint _DirectionalShadowIndex;
|
|
float4 _DirectionalLightDirection;
|
|
float4 _PunctualLightPosition;
|
|
float4 _ContactShadowParamsParameters;
|
|
float4 _ContactShadowParamsParameters2;
|
|
int _SampleCount;
|
|
CBUFFER_END
|
|
|
|
#define _ContactShadowLength _ContactShadowParamsParameters.x
|
|
#define _ContactShadowDistanceScaleFactor _ContactShadowParamsParameters.y
|
|
#define _ContactShadowFadeEnd _ContactShadowParamsParameters.z
|
|
#define _ContactShadowFadeOneOverRange _ContactShadowParamsParameters.w
|
|
#define _ContactShadowOpacity _ContactShadowParamsParameters2.x
|
|
|
|
#define DEFERRED_SHADOW_TILE_SIZE 16
|
|
|
|
// Return 1.0 if occluded 0.0 if not
|
|
float4 ScreenSpaceShadowRayCast(float3 positionWS, float3 rayDirection, float rayLength)
|
|
{
|
|
uint3 hashInput = uint3(abs(GetAbsolutePositionWS(positionWS)) * 1000);
|
|
// Dither pattern is shifted by 0.5 because we want to jitter the ray starting position backward and forward (so we need values between -0.5 and 0.5)
|
|
float ditherBias = 0.5;
|
|
float dither = GenerateHashedRandomFloat(hashInput) - ditherBias;
|
|
|
|
float3 rayStartWS = positionWS;
|
|
float3 rayEndWS = rayStartWS + rayDirection * rayLength;
|
|
|
|
float4 rayStartCS = TransformWorldToHClip(rayStartWS);
|
|
float4 rayEndCS = TransformWorldToHClip(rayEndWS);
|
|
|
|
// Here we compute a ray perpendicular to view space. This is the ray we use to compute the threshold for rejecting samples.
|
|
// This is done this way so that the threshold is less dependent of ray slope.
|
|
float4 rayOrthoViewSpace = rayStartCS + mul(GetViewToHClipMatrix(), float4(0, 0, rayLength, 0));
|
|
rayOrthoViewSpace = rayOrthoViewSpace / rayOrthoViewSpace.w;
|
|
|
|
rayStartCS.xyz = rayStartCS.xyz / rayStartCS.w;
|
|
rayEndCS.xyz = rayEndCS.xyz / rayEndCS.w;
|
|
|
|
// Pixel to light ray in clip space.
|
|
float3 rayCS = rayEndCS.xyz - rayStartCS.xyz;
|
|
|
|
// Depth at the start of the ray
|
|
float startDepth = rayStartCS.z;
|
|
// Depth range of the ray
|
|
float rayDepth = rayCS.z;
|
|
|
|
// Starting UV of the sampling loop
|
|
float2 startUV = rayStartCS.xy * 0.5f + 0.5f;
|
|
startUV.y = 1.0 - startUV.y;
|
|
|
|
// Pixel to light ray in
|
|
float2 rayUV = rayCS.xy * 0.5f;
|
|
rayUV.y = -rayUV.y;
|
|
|
|
float step = 1.0 / _SampleCount;
|
|
float compareThreshold = abs(rayOrthoViewSpace.z - rayStartCS.z) * step;
|
|
|
|
float occluded = 0.0f;
|
|
|
|
for (int i = 0; i < _SampleCount; i++)
|
|
{
|
|
// Step for this sample
|
|
float sampleStep = ((i + 1) * step + step * dither);
|
|
|
|
// UVs for the current sample
|
|
float2 sampleUV = (startUV + rayUV * sampleStep) * _ScreenToTargetScale.xy;
|
|
// Ray depth for this sample
|
|
float raySampleDepth = startDepth + rayDepth * sampleStep;
|
|
|
|
// Depth buffer depth for this sample
|
|
float sampleDepth = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, s_point_clamp_sampler, sampleUV, 0.0).x;
|
|
|
|
bool Hit = false;
|
|
float depthDiff = sampleDepth - raySampleDepth;
|
|
Hit = depthDiff < compareThreshold && depthDiff > 0.0;// 1e-4;
|
|
|
|
if (Hit)
|
|
occluded = 1.0f;
|
|
}
|
|
|
|
// Off screen masking
|
|
// We remove the occlusion if the ray is occluded and only if direction steps out of the screen
|
|
float2 vignette = max(6.0 * abs(rayStartCS.xy + rayCS.xy * occluded * 0.5) - 5.0, 0.0);
|
|
occluded *= saturate( 1.0 - dot(vignette, vignette) );
|
|
|
|
return occluded;
|
|
}
|
|
|
|
float ComputeContactShadow(PositionInputs posInput, float3 direction)
|
|
{
|
|
float contactShadow = 1.0;
|
|
|
|
if (_ContactShadowLength > 0.0f)
|
|
{
|
|
//Here LightDirection is not the light direction but the light position
|
|
float4 result = ScreenSpaceShadowRayCast(posInput.positionWS, direction, _ContactShadowLength * max(0.5, posInput.linearDepth * _ContactShadowDistanceScaleFactor));
|
|
contactShadow = 1.0 - result.x * saturate((_ContactShadowFadeEnd - posInput.linearDepth) * _ContactShadowFadeOneOverRange);
|
|
}
|
|
|
|
return lerp(1.0, contactShadow, _ContactShadowOpacity);
|
|
}
|
|
|
|
[numthreads(DEFERRED_SHADOW_TILE_SIZE, DEFERRED_SHADOW_TILE_SIZE, 1)]
|
|
void DEFERRED_DIRECTIONAL(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID)
|
|
{
|
|
uint2 pixelCoord = groupId * DEFERRED_SHADOW_TILE_SIZE + groupThreadId;
|
|
uint2 tileCoord = groupId;
|
|
float contactShadow = 1.0;
|
|
|
|
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, pixelCoord.xy).x;
|
|
|
|
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
|
|
return;
|
|
|
|
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
|
|
|
|
//Direction got from either the directional light direction or the difference of punctual light position and the pixel position
|
|
float3 direction = normalize(_DirectionalLightDirection.xyz * _DirectionalLightDirection.w + (_PunctualLightPosition.xyz - posInput.positionWS) * _PunctualLightPosition.w);
|
|
|
|
NormalData normalData;
|
|
DecodeFromNormalBuffer(posInput.positionSS, normalData);
|
|
float3 normalWS = normalData.normalWS;
|
|
|
|
ShadowContext shadowContext = InitShadowContext();
|
|
float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, normalWS, _DirectionalShadowIndex, _DirectionalLightDirection.xyz);
|
|
|
|
#ifdef ENABLE_CONTACT_SHADOWS
|
|
contactShadow = ComputeContactShadow(posInput, direction);
|
|
#endif
|
|
|
|
_DeferredShadowTextureUAV[pixelCoord] = float4(shadow, contactShadow, 1.0, 1.0); // Note: RT is RG16 format
|
|
}
|
|
|
|
[numthreads(DEFERRED_SHADOW_TILE_SIZE, DEFERRED_SHADOW_TILE_SIZE, 1)]
|
|
void DeferredContactShadow(uint2 groupThreadId : SV_GroupThreadID, uint2 groupId : SV_GroupID)
|
|
{
|
|
uint2 pixelCoord = groupId * DEFERRED_SHADOW_TILE_SIZE + groupThreadId;
|
|
uint2 tileCoord = groupId;
|
|
float contactShadow = 1.0;
|
|
|
|
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, pixelCoord.xy).x;
|
|
|
|
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
|
|
return;
|
|
|
|
PositionInputs posInput = GetPositionInput(pixelCoord.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V, tileCoord);
|
|
|
|
float3 direction = normalize(_PunctualLightPosition.xyz - posInput.positionWS);
|
|
|
|
contactShadow = ComputeContactShadow(posInput, direction);
|
|
|
|
_DeferredShadowTextureUAV[pixelCoord] = float4(1.0, contactShadow, 1.0, 1.0); // Note: RT is RG16 format
|
|
}
|