add additional water fog controls, centralize water absorbance into one file

This commit is contained in:
Xonk
2026-05-07 00:30:33 -04:00
parent 6ab277bc08
commit 7fe4573f45
6 changed files with 92 additions and 102 deletions
+8 -79
View File
@@ -182,6 +182,7 @@ float convertHandDepth_2(in float depth, bool hand) {
#include "/lib/diffuse_lighting.glsl"
#include "/lib/end_fog.glsl"
#include "/lib/DistantHorizons_projections.glsl"
#include "/lib/water_absorbance_effects.glsl"
float ld(float dist) {
return (2.0 * near) / (far + near - dist * (far - near));
@@ -912,8 +913,8 @@ void main() {
vec3 viewPos = toScreenSpace(vec3(texcoord/RENDER_SCALE - taaJitter*texelSize*0.5, z));
#endif
vec3 feetPlayerPos = mat3(gbufferModelViewInverse) * viewPos;
vec3 feetPlayerPos_normalized = normalize(feetPlayerPos);
vec3 feetPlayerPos = mat3(gbufferModelViewInverse) * viewPos + gbufferModelViewInverse[3].xyz;
vec3 feetPlayerPos_normalized = normalize(feetPlayerPos );
#ifdef POM
#ifdef Horrible_slope_normals
@@ -971,95 +972,23 @@ void main() {
//////////////////////////////// UNDER WATER SHADING ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
if ((isEyeInWater == 0 && isWater) || (isEyeInWater == 1 && !isWater)){
feetPlayerPos += gbufferModelViewInverse[3].xyz;
#ifdef USING_LOD_MOD
vec3 playerPos0 = mat3(gbufferModelViewInverse) * toScreenSpace_DH(texcoord/RENDER_SCALE-taaJitter*texelSize*0.5, z0, DH_depth0) + gbufferModelViewInverse[3].xyz;
#else
vec3 playerPos0 = mat3(gbufferModelViewInverse) * toScreenSpace(vec3(texcoord/RENDER_SCALE-taaJitter*texelSize*0.5,z0)) + gbufferModelViewInverse[3].xyz;
#endif
float Vdiff = distance(feetPlayerPos, playerPos0);
float estimatedDepth = Vdiff* abs(feetPlayerPos_normalized.y);// assuming water plane
// vec3 waterNormal = clamp(normalize(cross(dFdx(playerPos0), dFdy(playerPos0))),-1,1); // it uses depth that has POM written to it.
// vec3 absPlayerPosNorm = abs(feetPlayerPos_normalized);
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.y, max(waterNormal.y,0));
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.y, max(-waterNormal.y,0));
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.z, max(waterNormal.z,0));
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.z, max(-waterNormal.z,0));
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.x, max(waterNormal.x,0));
// estimatedDepth = mix(estimatedDepth, Vdiff*absPlayerPosNorm.x, max(-waterNormal.x,0));
// force the absorbance to start way closer to the water surface in low light areas, so the water is visible in caves and such.
#if MINIMUM_WATER_ABSORBANCE > -1
float minimumAbsorbance = MINIMUM_WATER_ABSORBANCE*0.1;
#else
float minimumAbsorbance = (1.0 - lightLeakFix);
#endif
Absorbtion = exp(-totEpsilon * max(Vdiff, minimumAbsorbance));
// things to note about sunlight in water
// sunlight gets absorbed by water on the way down to the floor, and on the way back up to your eye. im gonna ingore the latter part lol
// based on the angle of the sun, sunlight will travel through more/less water to reach the same spot. scale absorbtion depth accordingly
vec3 sunlightAbsorbtion = exp(-totEpsilon * (estimatedDepth/abs(WsunVec.y)));
float percievedWaterDepth = estimatedDepth;
if (isEyeInWater == 1){
estimatedDepth = 1.0;
// viewerWaterDepth = max(0.9-lightmap.y,0.0)*3.0;
float distanceFromWaterSurface = -(feetPlayerPos.y + (cameraPosition.y - waterEnteredAltitude));//max(-(feetPlayerPos.y + (cameraPosition.y - waterEnteredAltitude)),0.0) ;
percievedWaterDepth = distanceFromWaterSurface;
distanceFromWaterSurface = max(distanceFromWaterSurface,0.0);
Absorbtion = exp(-totEpsilon * distanceFromWaterSurface);
sunlightAbsorbtion = exp(-totEpsilon * (distanceFromWaterSurface/abs(WsunVec.y)));
} else {
// use hardcoded gradient position if the water surface normal does not face upwards.
// vec3 waterNormal = clamp(normalize(cross(dFdx(playerPos0), dFdy(playerPos0))),0,1); // it uses depth that has POM written to it.
// percievedWaterDepth = mix( -(feetPlayerPos.y + cameraPosition.y),percievedWaterDepth, waterNormal.y);
// artifacts too obvious unfortunately, go back to hardcoded
percievedWaterDepth = -(feetPlayerPos.y + cameraPosition.y);
}
DirectLightColor *= sunlightAbsorbtion;
if( nightVision > 0.0 ) Absorbtion += exp(-totEpsilon * 25.0) * nightVision;
// apply caustics to the lighting, and make sure they dont look weird
vec3 pos = feetPlayerPos + cameraPosition;
vec2 causticPos = pos.xz;
causticPos = mix(causticPos, pos.xz, max(FlatNormals.y,0));
// causticPos = mix(causticPos, pos.xy, max(-FlatNormals.y,0));
causticPos = mix(causticPos, pos.zy, max(FlatNormals.x,0));
causticPos = mix(causticPos, pos.xy, max(-FlatNormals.z,0));
// causticPos = mix(causticPos, pos.xy, max(FlatNormals.x,0));
// causticPos = mix(causticPos, pos.xy, max(-FlatNormals.x,0));
DirectLightColor *= pow(mix(1.0, waterCaustics(feetPlayerPos + cameraPosition, WsunVec, percievedWaterDepth)*WATER_CAUSTICS_BRIGHTNESS, clamp(estimatedDepth,0,1)), WATER_CAUSTICS_POWER);
underWaterAbsorbance_outsidePOV(
playerPos0, feetPlayerPos , feetPlayerPos_normalized,
WsunVec, // (normalize(cross(dFdx(feetPlayerPos ), dFdy(feetPlayerPos ))).y > 0.01 ? 1.0 : 0.0),
totEpsilon, Absorbtion, DirectLightColor, lightLeakFix
);
}
// albedo *= waterCaustics(feetPlayerPos + cameraPosition, WsunVec);
if (swappedDepth < 1.0) {
// idk why this do
feetPlayerPos += gbufferModelViewInverse[3].xyz;
////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// FILTER STUFF //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
+5 -4
View File
@@ -227,6 +227,7 @@ uniform sampler2D colortex4;
#ifdef END_SHADER
uniform sampler2D colortex4;
#include "/lib/end_fog.glsl"
// #include "/lib/end_volumetrics.glsl"
#endif
#define fsign(a) (clamp((a)*1e35,0.,1.)*2.-1.)
@@ -350,8 +351,8 @@ vec4 waterVolumetrics_insidePOV(vec3 rayStart, vec3 rayEnd, float rayLength, vec
float bubble = exp2(-10.0 * clamp(1.0 - length(d*dVWorld) / 16.0, 0.0,1.0));
float caustics = max(max(waterCaustics(progressW, WsunVec, -(progressW.y - waterEnteredAltitude)), phase*0.5) * mix(0.5, 1.5, bubble), phase);
vec3 sunAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface/abs(WsunVec.y)));
vec3 WaterAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface + thing));
vec3 sunAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface/abs(WsunVec.y)) * WATER_DEPTH_FREQUENCY_DIRECTLIGHT);
vec3 WaterAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface + thing) * WATER_DEPTH_FREQUENCY_INDIRECTLIGHT);
vec3 Directlight = lightSource * sh * phase * caustics * sunAbsorbance;
vec3 Indirectlight = ambient * WaterAbsorbance;
@@ -445,8 +446,8 @@ vec4 waterVolumetrics_outsidePOV( vec3 rayStart, vec3 rayEnd, float estEndDepth,
}
#endif
vec3 sunAbsorbance = exp(-waterCoefs * estSunDepth * d);
vec3 ambientAbsorbance = exp(-waterCoefs * (estEndDepth * d + thing));
vec3 sunAbsorbance = exp(-waterCoefs * estSunDepth * d * WATER_DEPTH_FREQUENCY_DIRECTLIGHT);
vec3 ambientAbsorbance = exp(-waterCoefs * (estEndDepth * d + thing) * WATER_DEPTH_FREQUENCY_INDIRECTLIGHT);
vec3 Directlight = lightSource * sh * cloudShadow * phase * sunAbsorbance;
vec3 Indirectlight = ambient * ambientAbsorbance;
+2 -15
View File
@@ -77,6 +77,7 @@ uniform float eyeAltitude;
#endif
#include "/lib/sky_gradient.glsl"
#include "/lib/water_absorbance_effects.glsl"
#define diagonal3(m) vec3((m)[0].x, (m)[1].y, m[2].z)
#define projMAD(m, v) (diagonal3(m) * (v) + (m)[3].xyz)
@@ -385,22 +386,8 @@ void blendAllFogTypes( inout vec3 color, inout float bloomyFogMult, vec4 volumet
#endif
/// water absorption; it is completed when volumetrics are blended.
if(isEyeInWater == 1){
vec3 totEpsilon = vec3(Water_Absorb_R, Water_Absorb_G, Water_Absorb_B);
vec3 scatterCoef = Dirt_Amount * vec3(Dirt_Scatter_R, Dirt_Scatter_G, Dirt_Scatter_B) / 3.14;
if(isEyeInWater == 1) underWaterAbsorbance_insidePOV(linearDistance, color, bloomyFogMult);
float distanceFromWaterSurface = playerPos.y + 1.0 + (cameraPosition.y - waterEnteredAltitude)/waterEnteredAltitude;
distanceFromWaterSurface = clamp(distanceFromWaterSurface,0,1);
vec3 transmittance = exp(-totEpsilon * linearDistance);
color.rgb *= transmittance;
vec3 transmittance2 = exp(-totEpsilon * 50.0);
float fogfade = 1.0 - max((1.0 - linearDistance / min(far, 16.0*7.0) ),0);
color.rgb += (transmittance2 * scatterCoef) * fogfade;
bloomyFogMult *= dot(transmittance,vec3(0.3333))*0.75 + 0.25;
}
/// blend volumetrics
color = color * volumetrics.a + volumetrics.rgb;
+6
View File
@@ -195,6 +195,12 @@
#define PATCHY_WAVE_BLEND 1.0 // [0.0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.0]
#define WAVES_A_RADIUS 1.0 // [0.0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.0 2.0 3.0 4.0 5.0]
#define WAVES_B_RADIUS 0.15 // [0.0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.0 2.0 3.0 4.0 5.0]
#define WATER_DEPTH_FREQUENCY_DIRECTLIGHT 1.0 // [0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
#define WATER_DEPTH_FREQUENCY_INDIRECTLIGHT 1.0 // [0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
#define WATER_DEPTH_FREQUENCY_ALL_LIGHT 1.0 // [0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
#define MINIMUM_UNDERWATER_FOG_BRIGHTNESS 1.0 // [0.0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0 45.0 50.0 100.0]
#endif
#if defined EXPOSURE_RELATED_SETTINGS
+67
View File
@@ -0,0 +1,67 @@
void underWaterAbsorbance_outsidePOV(
in vec3 playerPos_depthtex0, in vec3 playerPos_depthtex1, in vec3 playerPos_n,
in vec3 sunVector,
in vec3 totEpsilon,
inout vec3 absorbance, inout vec3 directLightColor, in float lightLeakFix
){
// theres 2 absorbances being done here.
// absorbance for the cameras POV into the water
// absorbance for the sunlight itself as it travels through the volume to the point it hits a surface, and then the former absorbance is applied on top of that.
// force the absorbance to start way closer to the water surface in low light areas, so the water is visible in caves and such.
#if MINIMUM_WATER_ABSORBANCE > -1
float minimumAbsorbance = MINIMUM_WATER_ABSORBANCE*0.1;
#else
float minimumAbsorbance = 1.0 - lightLeakFix;
#endif
// get the difference of playerpos with depthtex0 and depthtex1, to get the distance starting at the water surface.
float distanceDiff = distance(playerPos_depthtex1, playerPos_depthtex0);
// fix the gradient to be perfectly vertical in meters.
float estimatedWaterDepth = distanceDiff * abs(playerPos_n.y);
// the distance the sunlight has travelled through water.
float travelledWaterDepth = estimatedWaterDepth;
if (isEyeInWater == 1){
minimumAbsorbance = 0.0;
estimatedWaterDepth = 1.0;
travelledWaterDepth = -(playerPos_depthtex1.y + (cameraPosition.y - waterEnteredAltitude));
}
absorbance = exp(-totEpsilon * max(distanceDiff, minimumAbsorbance) * WATER_DEPTH_FREQUENCY_ALL_LIGHT);
if( nightVision > 0.0 ) absorbance += exp(-totEpsilon * 25.0) * nightVision;
// things to note about sunlight in water
// sunlight gets absorbed by water on the way down to the floor, and on the way back up to your eye. im gonna ingore the latter part lol
// based on the angle of the sun, sunlight will travel through more/less water to reach the same spot. scale absorbtion depth accordingly
vec3 directLightAbsorbance = exp(-totEpsilon * (max(travelledWaterDepth,0.0)/abs(sunVector.y)) * WATER_DEPTH_FREQUENCY_DIRECTLIGHT);
// this is a quick fix for the water depth offset for projecting caustics. the sides of water have unsable water depth info (its the wrong angle) for this usecase, so fallback to a hardcoded height gradient
if (isEyeInWater == 0) travelledWaterDepth = -(playerPos_depthtex1.y + (cameraPosition.y - 63.0));
float waterCaustics = waterCaustics(playerPos_depthtex1 + cameraPosition, sunVector, travelledWaterDepth);
waterCaustics *= WATER_CAUSTICS_BRIGHTNESS;
waterCaustics = mix(1.0, waterCaustics, clamp(estimatedWaterDepth,0.0,1.0));
waterCaustics = pow(waterCaustics, WATER_CAUSTICS_POWER);
directLightColor *= directLightAbsorbance * waterCaustics;
}
void underWaterAbsorbance_insidePOV(
in float linearDistance,
inout vec3 sceneColor, inout float bloomyFogMult
){
vec3 totEpsilon = vec3(Water_Absorb_R, Water_Absorb_G, Water_Absorb_B);
vec3 scatterCoef = Dirt_Amount * vec3(Dirt_Scatter_R, Dirt_Scatter_G, Dirt_Scatter_B) / 3.14;
vec3 transmittance = exp(-totEpsilon * linearDistance * WATER_DEPTH_FREQUENCY_ALL_LIGHT);
vec3 transmittance2 = exp(-totEpsilon * 50.0);
float fogfade = 1.0 - max((1.0 - linearDistance / min(far, 16.0*7.0) ),0);
sceneColor *= transmittance;
sceneColor += (transmittance2 * scatterCoef) * fogfade * MINIMUM_UNDERWATER_FOG_BRIGHTNESS;
bloomyFogMult *= dot(transmittance,vec3(0.3333))*0.75 + 0.25;
}
File diff suppressed because one or more lines are too long