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.
 
 
 
 
 

82 lines
3.5 KiB

#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
// Shadows
#pragma kernel TraceVolumetricCloudsShadows
#pragma multi_compile _ CLOUDS_SIMPLE_PRESET
// #pragma enable_d3d11_debug_symbols
#define TRACE_CLOUDS_SHADOWS 1
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricClouds/VolumetricCloudsUtilities.hlsl"
RW_TEXTURE2D(float4, _VolumetricCloudsShadowRW);
[numthreads(8, 8, 1)]
void TraceVolumetricCloudsShadows(uint3 currentCoords : SV_DispatchThreadID, int groupIndex : SV_GroupIndex)
{
// If we can, load the cloud lut into the LDS
#if defined(CLOUDS_SIMPLE_PRESET)
LoadCloudLutToLDS(groupIndex);
#endif
// Compute the normalized coordinate on the shadow plane
float2 normalizedCoord = currentCoords.xy / (float)(_ShadowCookieResolution - 1);
// Compute the origin of the ray properties in the planet space
float3 rayOriginPS = _CloudShadowSunOrigin.xyz + (normalizedCoord.x * _CloudShadowSunRight.xyz + normalizedCoord.y * _CloudShadowSunUp.xyz);
float3 rayDirection = _CloudShadowSunForward.xyz;
// Compute the attenuation
float transmittance = 1.0f;
float closestDistance = FLT_MAX;
float farthestDistance = 0.0;
bool validShadow = false;
// Intersect the outer sphere
float radialDistance = length(rayOriginPS);
float cosChi = dot(rayOriginPS, rayDirection) * rcp(radialDistance);
float2 tInner = IntersectSphere(_LowestCloudAltitude, cosChi, radialDistance);
float2 tOuter = IntersectSphere(_HighestCloudAltitude, cosChi, radialDistance);
if (tInner.y >= 0.0 && tOuter.y >= 0.0)
{
// Compute the integration range
float startDistance = tInner.y;
float totalDistance = tOuter.y - tInner.y;
float stepSize = totalDistance / 16;
for (int i = 1; i < 16; ++i)
{
// Compute the sphere intersection position
float dist = (startDistance + stepSize * i);
float3 positionPS = rayOriginPS + rayDirection * dist;
// Get the coverage at intersection point
CloudCoverageData cloudCoverageData;
GetCloudCoverageData(positionPS, cloudCoverageData);
// Compute the cloud density
CloudProperties cloudProperties;
EvaluateCloudProperties(positionPS, 0.0, 0.0, true, true, cloudProperties);
// Apply the camera fade it to match the clouds perceived by the camera
cloudProperties.density *= DensityFadeValue(length(positionPS - _CameraPositionPS.xyz));
if (cloudProperties.density > CLOUD_DENSITY_TRESHOLD)
{
// Apply the extinction
closestDistance = min(closestDistance, startDistance + stepSize * (i - 1));
farthestDistance = max(farthestDistance, startDistance + stepSize * i);
const float3 currentStepExtinction = exp(-_ScatteringTint.xyz * cloudProperties.density * cloudProperties.sigmaT * stepSize);
transmittance *= Luminance(currentStepExtinction);
validShadow = true;
}
}
}
// If we didn't manage to hit a non null density, we need to fix the distances
float4 result = validShadow ? float4(1.0 / closestDistance, lerp(1.0 - _ShadowIntensity, 1.0, transmittance), 1.0 / farthestDistance, 1.0) : float4(0.0, 1.0, 0.0, 0.0);
_VolumetricCloudsShadowRW[currentCoords.xy] = result;
}