mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 18:56:16 +03:00
198 lines
7.6 KiB
GLSL
198 lines
7.6 KiB
GLSL
|
|
#version 460
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
#extension GL_EXT_samplerless_texture_functions : enable
|
|
|
|
#include "cloud_common.glsl"
|
|
|
|
vec3 drawSun(vec3 rayDir, vec3 sunDir)
|
|
{
|
|
const float dT = dot(rayDir, sunDir);
|
|
|
|
const float theta = 0.1 * kPI / 180.0;
|
|
const vec3 sunCenterColor = vec3(1.0f, 0.92549, 0.87843) * 39.0f * 100;
|
|
|
|
const float cT = cos(theta);
|
|
if (dT >= cT)
|
|
{
|
|
return sunCenterColor;
|
|
}
|
|
|
|
return vec3(0.0);
|
|
}
|
|
|
|
|
|
layout (local_size_x = 8, local_size_y = 8) in;
|
|
void main()
|
|
{
|
|
ivec2 texSize = imageSize(imageHdrSceneColor);
|
|
ivec2 depthTextureSize = textureSize(inDepth, 0);
|
|
ivec2 workPos = ivec2(gl_GlobalInvocationID.xy);
|
|
|
|
if(workPos.x >= texSize.x || workPos.y >= texSize.y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const vec2 uv = (vec2(workPos) + vec2(0.5f)) / vec2(texSize);
|
|
|
|
// Offset retarget for new seeds each frame
|
|
uvec2 offset = uvec2(vec2(0.754877669, 0.569840296) * (frameData.frameIndex.x) * uvec2(texSize));
|
|
uvec2 offsetId = workPos.xy + offset;
|
|
offsetId.x = offsetId.x % texSize.x;
|
|
offsetId.y = offsetId.y % texSize.y;
|
|
float blueNoise2 = samplerBlueNoiseErrorDistribution_128x128_OptimizedFor_2d2d2d2d(offsetId.x, offsetId.y, 0, 0u);
|
|
|
|
vec4 clipSpace = vec4(uv.x * 2.0f - 1.0f, 1.0f - uv.y * 2.0f, 0.0, 1.0);
|
|
vec4 viewPosH = frameData.camInvertProj * clipSpace;
|
|
vec3 viewDir = viewPosH.xyz / viewPosH.w;
|
|
vec3 worldDir = normalize((frameData.camInvertView * vec4(viewDir, 0.0)).xyz);
|
|
|
|
vec4 srcColor = imageLoad(imageHdrSceneColor, workPos);
|
|
float sceneZ = texture(sampler2D(inDepth, pointClampEdgeSampler), uv).r;
|
|
// vec4 cloudColor = kuwaharaFilter(inCloudReconstructionTexture, linearClampEdgeSampler,uv);
|
|
|
|
|
|
vec4 cloudColor = texture(sampler2D(inCloudReconstructionTexture, linearClampEdgeSampler), uv);
|
|
vec4 fogColor = texture(sampler2D(inCloudFogReconstructionTexture, linearClampEdgeSampler), uv);
|
|
|
|
float cloudDepth = texture(sampler2D(inCloudDepthReconstructionTexture, linearClampEdgeSampler), uv).r;
|
|
cloudDepth = max(1e-5f, cloudDepth); // very far cloud may be negative, use small value is enough.
|
|
|
|
vec3 result = srcColor.rgb;
|
|
|
|
if(sceneZ <= 0.0f) // reverse z.
|
|
{
|
|
// Composite planar cloud.
|
|
|
|
result = srcColor.rgb * cloudColor.a + cloudColor.rgb;
|
|
|
|
if(fogColor.a >= 0.0f)
|
|
{
|
|
result.rgb = result.rgb * fogColor.a + max(vec3(0.0f), fogColor.rgb);
|
|
}
|
|
}
|
|
|
|
{
|
|
const uint kGodRaySteps = 64;
|
|
const float kMaxMarchingDistance = 400.0f;
|
|
|
|
// We are revert z.
|
|
vec4 clipSpace = vec4(uv.x * 2.0f - 1.0f, 1.0f - uv.y * 2.0f, 0.0, 1.0);
|
|
vec4 viewPosH = frameData.camInvertProj * clipSpace;
|
|
vec3 viewSpaceDir = viewPosH.xyz / viewPosH.w;
|
|
vec3 worldDir = normalize((frameData.camInvertView * vec4(viewSpaceDir, 0.0)).xyz);
|
|
|
|
|
|
AtmosphereParameters atmosphere = getAtmosphereParameters(frameData);
|
|
const SkyInfo sky = frameData.sky;
|
|
vec3 worldPosWP = getWorldPos(uv, sceneZ, frameData);
|
|
vec3 pixelToCameraWP = frameData.camWorldPos.xyz - worldPosWP;
|
|
|
|
float pixelToCameraDistanceWP = max(1e-5f, length(pixelToCameraWP));
|
|
vec3 rayDirWP = pixelToCameraWP / pixelToCameraDistanceWP;
|
|
|
|
float marchingDistance = min(kMaxMarchingDistance, pixelToCameraDistanceWP);
|
|
if(pixelToCameraDistanceWP > kMaxMarchingDistance)
|
|
{
|
|
worldPosWP = frameData.camWorldPos.xyz - rayDirWP * marchingDistance;
|
|
}
|
|
|
|
vec3 sunDirection = -normalize(frameData.sky.direction);
|
|
float VoL = dot(worldDir, sunDirection);
|
|
|
|
float stepLength = marchingDistance / float(kGodRaySteps);
|
|
vec3 stepRay = rayDirWP * stepLength;
|
|
|
|
// Interval noise is better than blue noise here.
|
|
float taaOffset = interleavedGradientNoise(workPos, frameData.frameIndex.x % frameData.jitterPeriod);
|
|
|
|
vec3 rayPosWP = worldPosWP + stepRay * (blueNoise2 + 0.05);
|
|
|
|
float transmittance2 = 1.0;
|
|
vec3 scatteredLight2 = vec3(0.0, 0.0, 0.0);
|
|
|
|
float miePhaseValue = hgPhase(atmosphere.miePhaseG, -VoL);
|
|
float rayleighPhaseValue = rayleighPhase(VoL);
|
|
vec3 sunColor = frameData.sky.color * frameData.sky.intensity;
|
|
vec3 groundToCloudTransfertIsoScatter = texture(samplerCube(inSkyIrradiance, linearClampEdgeSampler), vec3(0, 1, 0)).rgb;
|
|
|
|
for(uint i = 0; i < kGodRaySteps; i ++)
|
|
{
|
|
float visibilityTerm = 1.0;
|
|
{
|
|
// First find active cascade.
|
|
uint activeCascadeId = 0;
|
|
vec3 shadowCoord;
|
|
|
|
// Loop to find suitable cascade.
|
|
for(uint cascadeId = 0; cascadeId < sky.cacsadeConfig.cascadeCount; cascadeId ++)
|
|
{
|
|
shadowCoord = projectPos(rayPosWP, cascadeInfos[cascadeId].viewProj);
|
|
if(onRange(shadowCoord.xyz, vec3(sky.cacsadeConfig.cascadeBorderAdopt), vec3(1.0f - sky.cacsadeConfig.cascadeBorderAdopt)))
|
|
{
|
|
break;
|
|
}
|
|
activeCascadeId ++;
|
|
}
|
|
|
|
if(activeCascadeId < sky.cacsadeConfig.cascadeCount)
|
|
{
|
|
const float perCascadeOffsetUV = 1.0f / sky.cacsadeConfig.cascadeCount;
|
|
const float shadowTexelSize = 1.0f / float(sky.cacsadeConfig.percascadeDimXY);
|
|
|
|
// Main cascsade shadow compute.
|
|
{
|
|
vec3 shadowPosOnAltas = shadowCoord;
|
|
|
|
// Also add altas bias and z bias.
|
|
shadowPosOnAltas.x = (shadowPosOnAltas.x + float(activeCascadeId)) * perCascadeOffsetUV;
|
|
shadowPosOnAltas.z += 0.001 * (activeCascadeId + 1.0);
|
|
|
|
float depthShadow = texture(sampler2D(inSDSMShadowDepth, pointClampEdgeSampler), shadowPosOnAltas.xy).r;
|
|
visibilityTerm = shadowPosOnAltas.z > depthShadow ? 1.0 : 0.0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Second evaluate transmittance due to participating media
|
|
vec3 atmosphereTransmittance;
|
|
{
|
|
vec3 P0 = rayPosWP * 0.001 + vec3(0.0, atmosphere.bottomRadius, 0.0); // meter -> kilometers.
|
|
float viewHeight = length(P0);
|
|
const vec3 upVector = P0 / viewHeight;
|
|
|
|
float viewZenithCosAngle = dot(sunDirection, upVector);
|
|
vec2 sampleUv;
|
|
lutTransmittanceParamsToUv(atmosphere, viewHeight, viewZenithCosAngle, sampleUv);
|
|
atmosphereTransmittance = texture(sampler2D(inTransmittanceLut, linearClampEdgeSampler), sampleUv).rgb;
|
|
}
|
|
|
|
float density = getDensity(distance(rayPosWP, frameData.camWorldPos.xyz));
|
|
|
|
float sigmaS = density;
|
|
float sigmaE = max(sigmaS, 1e-8f);
|
|
|
|
|
|
vec3 phaseTimesScattering = vec3(miePhaseValue + rayleighPhaseValue);
|
|
vec3 sunSkyLuminance = groundToCloudTransfertIsoScatter + visibilityTerm * sunColor * phaseTimesScattering * atmosphereTransmittance;
|
|
|
|
vec3 sactterLitStep = sunSkyLuminance * sigmaS;
|
|
|
|
float stepTransmittance = exp(-sigmaE * stepLength);
|
|
scatteredLight2 += transmittance2 * (sactterLitStep - sactterLitStep * stepTransmittance) / sigmaE;
|
|
transmittance2 *= stepTransmittance;
|
|
|
|
// Step.
|
|
rayPosWP += stepRay;
|
|
}
|
|
|
|
result.rgb = result.rgb * transmittance2 + scatteredLight2;
|
|
}
|
|
|
|
|
|
|
|
|
|
imageStore(imageHdrSceneColor, workPos, vec4(result.rgb, 1.0));
|
|
} |