1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2026-01-31 18:18:26 +00:00

Makes refraction mixing based on water depth, fixes underwater fog misalignment near shores, allows underwater fog to be radial with reverse-Z

This commit is contained in:
Qlonever 2023-04-11 20:59:52 -04:00 committed by elsid
parent e5e117a186
commit 7628c23750
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625

View file

@ -40,7 +40,7 @@ const float REFL_BUMP = 0.10; // reflection distortion amou
const float REFR_BUMP = 0.07; // refraction distortion amount
const float SCATTER_AMOUNT = 0.3; // amount of sunlight scattering
const vec3 SCATTER_COLOUR = vec3(0.0,1.0,0.95); // colour of sunlight scattering
const vec3 SCATTER_COLOR = vec3(0.0,1.0,0.95); // color of sunlight scattering
const vec3 SUN_EXT = vec3(0.45, 0.55, 0.68); //sunlight extinction
@ -148,9 +148,11 @@ void main(void)
#if @radialFog
float radialDepth = distance(position.xyz, cameraPos);
// TODO: Figure out how to properly radialise refraction depth and thus underwater fog
// TODO: Figure out how to properly radialise refraction depth and thus underwater fog
// while avoiding oddities when the water plane is close to the clipping plane
// radialise = radialDepth / linearDepth;
#if @reverseZ
radialise = radialDepth / linearDepth;
#endif
#else
float radialDepth = 0.0;
#endif
@ -158,10 +160,11 @@ void main(void)
vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
#if REFRACTION
float depthSample = linearizeDepth(sampleRefractionDepthMap(screenCoords), near, far) * radialise;
float depthSampleDistorted = linearizeDepth(sampleRefractionDepthMap(screenCoords-screenCoordsOffset), near, far) * radialise;
float surfaceDepth = linearizeDepth(gl_FragCoord.z, near, far) * radialise;
float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum
screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1);
float depthSampleDistorted = linearizeDepth(sampleRefractionDepthMap(screenCoords - screenCoordsOffset), near, far) * radialise;
float waterDepthDistorted = depthSampleDistorted - surfaceDepth;
#endif
// reflection
vec3 reflection = sampleReflectionMap(screenCoords + screenCoordsOffset).rgb;
@ -187,9 +190,11 @@ void main(void)
// brighten up the refraction underwater
if (cameraPos.z < 0.0)
refraction = clamp(refraction * 1.5, 0.0, 1.0);
refraction = clamp(mix(refraction, waterColor, clamp(1.0 / (surfaceDepth * VISIBILITY), 0.0, 1.0)) * 1.5, 0.0, 1.0);
else
refraction = mix(refraction, waterColor, clamp(depthSampleDistorted/VISIBILITY, 0.0, 1.0));
// a rational curve rising from 0 to 1 between 0 and VISIBILITY units of depth
// refraction = mix(refraction, waterColor, clamp((-1.0 / (waterDepthDistorted / (VISIBILITY * DEPTH_FADE) + (-1 + sqrt(1.0 + 4.0 * DEPTH_FADE * DEPTH_FADE)) / (2.0 * DEPTH_FADE)) + (-1.0 + sqrt(1.0 + 4.0 * DEPTH_FADE * DEPTH_FADE)) / (2.0 * DEPTH_FADE)) * DEPTH_FADE + 1.0, 0.0, 1.0));
refraction = mix(refraction, waterColor, clamp(-1.0 * VISIBILITY /(25.0 * waterDepthDistorted + 0.96291 * VISIBILITY) + 1.03852, 0.0, 1.0)); // an optimized version of the above function, assuming 0.2 for DEPTH_FADE
// sunlight scattering
// normal for sunlight scattering
@ -197,10 +202,10 @@ void main(void)
normal3 * midWaves.y * 0.2 + normal4 * smallWaves.x * 0.1 + normal5 * smallWaves.y * 0.1 + rippleAdd);
lNormal = normalize(vec3(-lNormal.x * bump, -lNormal.y * bump, lNormal.z));
float sunHeight = lVec.z;
vec3 scatterColour = mix(SCATTER_COLOUR*vec3(1.0,0.4,0.0), SCATTER_COLOUR, clamp(1.0-exp(-sunHeight*SUN_EXT), 0.0, 1.0));
vec3 scatterColor = mix(SCATTER_COLOR*vec3(1.0,0.4,0.0), SCATTER_COLOR, clamp(1.0-exp(-sunHeight*SUN_EXT), 0.0, 1.0));
vec3 lR = reflect(lVec, lNormal);
float lightScatter = clamp(dot(lVec,lNormal)*0.7+0.3, 0.0, 1.0) * clamp(dot(lR, vVec)*2.0-1.2, 0.0, 1.0) * SCATTER_AMOUNT * sunFade * clamp(1.0-exp(-sunHeight), 0.0, 1.0);
gl_FragData[0].xyz = mix( mix(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * sunSpec.xyz + rainSpecular;
gl_FragData[0].xyz = mix( mix(refraction, scatterColor, lightScatter), reflection, fresnel) + specular * sunSpec.xyz + rainSpecular;
gl_FragData[0].w = 1.0;
// wobbly water: hard-fade into refraction texture at extremely low depth, with a wobble based on normal mapping