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