Files

81 lines
2.3 KiB
GLSL

// MinecraftPT — Volumetric_FS
// Volumetric fog + volumetric clouds ray marched per-pixel and composited.
#include "/Lib/Settings.glsl"
#include "/Lib/Utilities.glsl"
#include "/Lib/BasicFunctions/LightingConstants.glsl"
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
#include "/Lib/IndividualFunctions/VolumetricFog.glsl"
#include "/Lib/IndividualFunctions/WaterFog.glsl"
#include "/Lib/IndividualFunctions/PlanarClouds.glsl"
#include "/Lib/IndividualFunctions/CloudShadow.glsl"
uniform sampler2D colortex12; // HDR scene
layout(location = 0) out vec4 colorOut;
void main(){
vec2 texelCoord = gl_FragCoord.xy;
vec3 sceneColor = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
float depth = texelFetch(depthtex0, ivec2(texelCoord), 0).r;
// Reconstruct view position
vec4 viewPos = gbufferProjectionInverse * vec4(texelCoord / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
viewPos.xyz /= viewPos.w;
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
// Dithering for the ray march
float dither = BlueNoiseTemporal();
// Volumetric fog accumulation
vec3 fogColor = vec3(0.0);
float transmittance = 1.0;
// Ray march toward the surface
int steps = VFOG_QUALITY;
float dist = length(viewPos.xyz);
float stepSize = dist / float(steps);
vec3 rayDir = normalize(viewPos.xyz);
vec3 marchPos = worldPos;
float time = frameTimeCounter * 0.05;
for (int i = 0; i < steps; i++){
float t = (float(i) + dither) * stepSize;
vec3 samplePos = marchPos - rayDir * t;
float density = GetVolumetricFogDensity(samplePos, time);
density *= stepSize;
// Sun scattering
float phase = 0.5 + 0.5 * dot(normalize(GetSunDirWorld()), -rayDir);
vec3 inscatter = GetFogColor(samplePos, GetSunDirWorld()) * density * phase;
fogColor += transmittance * inscatter;
transmittance *= exp(-density);
}
// Cloud shadow on fog
#ifdef VFOG_CLOUD_SHADOW
float cloudShadow = GetCloudShadow(worldPos);
fogColor *= cloudShadow;
#endif
// Combine
vec3 finalColor = sceneColor * transmittance + fogColor;
// Water fog (underwater)
#ifdef UNDERWATER_VFOG
if (isEyeInWater > 0){
vec3 waterColor = GetWaterFogColor(worldPos);
float waterFog = 1.0 - exp(-dist * GetWaterFogDensity(worldPos) * UNDERWATER_VFOG_DENSITY);
finalColor = mix(finalColor, waterColor * 3.0, waterFog);
}
#endif
colorOut = vec4(finalColor, 1.0);
}