522 lines
18 KiB
GLSL
522 lines
18 KiB
GLSL
// ocean-frag-ellipsoid-fft.glsl
|
|
#define DETAIL
|
|
#define DETAIL_OCTAVE 2.0
|
|
#define DETAIL_BLEND 0.4
|
|
//#define VISUALIZE_HEIGHT
|
|
#define SPECULAR_BOOST 500.0
|
|
#define SPECULAR_DISTANCE_FACTOR 70.0
|
|
#define BUBBLES 0.1
|
|
|
|
#ifdef OPENGL32
|
|
in vec3 V;
|
|
in vec2 foamTexCoords;
|
|
in vec2 texCoords;
|
|
in vec2 noiseTexCoords;
|
|
in vec3 up;
|
|
in vec4 wakeNormalsAndFoam;
|
|
in float fogFactor;
|
|
in float transparency;
|
|
in float depth;
|
|
#ifdef BREAKING_WAVES
|
|
in float breaker;
|
|
in float breakerFade;
|
|
in vec2 breakerTexCoords;
|
|
#endif
|
|
#ifdef PROPELLER_WASH
|
|
in vec3 washTexCoords;
|
|
in float activeWashWidth;
|
|
#endif
|
|
#ifdef LEEWARD_DAMPENING
|
|
in float leewardDampening;
|
|
#endif
|
|
in vec4 vVertex_Eye_Space;
|
|
in vec4 vVertex_Projection_Space;
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
in vec3 propWashCoords;
|
|
in vec3 localPropWashCoords;
|
|
#endif
|
|
#else
|
|
varying vec3 V;
|
|
varying vec2 foamTexCoords;
|
|
varying vec2 texCoords;
|
|
varying vec2 noiseTexCoords;
|
|
varying vec3 up;
|
|
varying vec4 wakeNormalsAndFoam;
|
|
varying float fogFactor;
|
|
varying float transparency;
|
|
varying float depth;
|
|
#ifdef BREAKING_WAVES
|
|
varying float breaker;
|
|
varying float breakerFade;
|
|
varying vec2 breakerTexCoords;
|
|
#endif
|
|
#ifdef PROPELLER_WASH
|
|
varying vec3 washTexCoords;
|
|
varying float activeWashWidth;
|
|
#endif
|
|
#ifdef LEEWARD_DAMPENING
|
|
varying float leewardDampening;
|
|
#endif
|
|
varying vec4 vVertex_Projection_Space;
|
|
varying vec4 vVertex_Eye_Space;
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
varying vec3 propWashCoords;
|
|
varying vec3 localPropWashCoords;
|
|
#endif
|
|
#endif
|
|
|
|
// From user-functions.glsl:
|
|
void user_lighting(in vec3 L
|
|
, in vec3 vVertex_World_Space, in vec3 vNormal_World_Space
|
|
, in vec4 vVertex_Projection_Space
|
|
, in float shininess
|
|
, inout vec3 ambient, inout vec3 diffuse, inout vec3 specular
|
|
);
|
|
void user_fog(in vec3 vNorm, inout vec4 waterColor, inout vec4 fogColor, inout float fogBlend);
|
|
void user_tonemap(in vec4 preToneMapColor, inout vec4 postToneMapColor);
|
|
void user_reflection_adjust(in vec4 envColor, in vec4 planarColor, in float planarReflectionBlend, inout vec4 reflectedColor);
|
|
float user_cloud_shadow_fragment();
|
|
void writeFragmentData(in vec4 finalColor, in vec4 Cdiffuse, in vec3 lightColor, in vec3 nNorm);
|
|
void user_diffuse_color( inout vec3 Cdiffuse, in vec3 CiNoLight, in vec3 Cwash, in vec4 reflectedColor,
|
|
in float reflectivity, in vec3 nNorm );
|
|
|
|
float finalWashWidth;
|
|
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
vec3 applyPropWash(in vec3 v, in vec3 localPos, in vec3 finalAmbient)
|
|
{
|
|
vec3 texCoords = vec3(0.0, 0.0, 0.0);
|
|
finalWashWidth = -1.0;
|
|
|
|
vec3 Cw = vec3(0.0, 0.0, 0.0);
|
|
#ifdef PROPELLER_WASH
|
|
|
|
float numHits = 0.0;
|
|
for (int i = 0; i < trit_numPropWashes; i++) {
|
|
|
|
//if (trit_washes[i].distFromSource == 0) continue;
|
|
|
|
vec3 C = trit_washes[i].deltaPos;
|
|
vec3 A = localPos - trit_washes[i].propPosition;
|
|
float segmentLength = length(C);
|
|
|
|
// Compute t
|
|
float t0 = dot(C, A) / dot(C, C);
|
|
|
|
// Compute enough overlap to account for curved paths.
|
|
float overlap = (trit_washes[i].washWidth / segmentLength) * 0.5;
|
|
|
|
if (t0 >= -overlap && t0 <= 1.0 + overlap) {
|
|
|
|
// Compute distance from source
|
|
float distFromSource = trit_washes[i].distFromSource - (1.0 - t0) * segmentLength;
|
|
|
|
// Compute wash width
|
|
float washWidth = (trit_washes[i].washWidth * pow(distFromSource, 1.0 / 4.5)) * 0.5;
|
|
|
|
// Compute distance to line
|
|
vec3 B = A - C;
|
|
vec3 aCrossB = cross(A, B);
|
|
float d = length(aCrossB) / segmentLength;
|
|
|
|
// The direction of A X B indicates if we're 'left' or 'right' of the path
|
|
float nd = d / washWidth;
|
|
|
|
if (clamp(nd, 0.0, 1.0) == nd) {
|
|
float t = t0;
|
|
if(nd >= 0.0 && nd <= 1.0) {
|
|
if(dot(up, aCrossB) >= 0.0) {
|
|
t = (1.0-nd*0.5)-0.5;
|
|
} else {
|
|
t = 0.5+(nd*0.5);
|
|
}
|
|
}
|
|
|
|
nd = t;
|
|
|
|
texCoords.x = nd;
|
|
// The t0 parameter from our initial distance test to the line segment makes
|
|
// for a handy t texture coordinate
|
|
|
|
//scale texture by 4 to reduce tiling
|
|
texCoords.y = (trit_washes[i].washLength - distFromSource) / (4.0*trit_washes[i].washWidth);
|
|
|
|
// We stuff the blend factor into the r coordinate.
|
|
|
|
//float blend = max(0.0, 1.0 - distFromSource / (trit_washLength));
|
|
float blend = mix(trit_washes[i].alphaEnd, trit_washes[i].alphaStart, t0);
|
|
|
|
if(t < 0.1) {
|
|
blend *= max(0.0, 10.0*t);
|
|
} else if(t > 0.9) {
|
|
blend *= max(0.0, (1.0-t)*10.0);
|
|
}
|
|
|
|
texCoords.z = clamp(blend, 0.0, 1.0);
|
|
|
|
finalWashWidth = trit_washes[i].washWidth;
|
|
|
|
#ifdef OPENGL32
|
|
Cw += texture(trit_washTex, texCoords.xy).xyz * finalAmbient * texCoords.z;
|
|
#else
|
|
Cw += texture2D(trit_washTex, texCoords.xy).xyz * finalAmbient * texCoords.z;
|
|
#endif
|
|
numHits += 1.0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return numHits > 0.0 ? Cw / numHits : Cw;
|
|
}
|
|
#endif
|
|
|
|
void main()
|
|
{
|
|
#ifdef VISUALIZE_HEIGHT
|
|
float r = (-depth / 100.0) + 0.5;
|
|
r = clamp(r, 0.0, 1.0);
|
|
gl_FragColor = vec4(r, r, r, 1.0);
|
|
return;
|
|
#endif
|
|
|
|
bool hasHeightMap = (trit_hasHeightMap || trit_hasUserHeightMap);
|
|
|
|
if ( hasHeightMap && depth < 0.0) {
|
|
discard;
|
|
return;
|
|
}
|
|
|
|
if (trit_depthOnly) {
|
|
#ifdef OPENGL32
|
|
writeFragmentData(vec4(0.0,0.0,0.0,1.0), vec4(0.0,0.0,0.0,0.0), trit_lightColor, vec3(0.0,0.0,0.0));
|
|
#else
|
|
gl_FragColor = vec4(0.0,0.0,0.0,1.0);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
const float IOR = 1.34;
|
|
|
|
float tileFade = exp(-length(V) * trit_invNoiseDistance);
|
|
float horizDist = length((trit_basis * V).xy);
|
|
float horizDistNorm = horizDist * trit_invNoiseDistance;
|
|
float tileFadeHoriz = exp(-horizDistNorm);
|
|
|
|
vec3 vNorm = normalize(V);
|
|
|
|
vec3 localEast = normalize(cross(trit_northPole, up));
|
|
vec3 localNorth = (cross(up, localEast));
|
|
|
|
#ifdef OPENGL32
|
|
|
|
#ifdef HIGHALT
|
|
vec4 slopesAndFoamHigh = texture(trit_slopeFoamMap, texCoords, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamMed = texture(trit_slopeFoamMap, (texCoords + 0.1) * 0.25, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamLow = texture(trit_slopeFoamMap, (texCoords + 0.7) * 0.125, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamReallyLow = texture(trit_slopeFoamMap, (texCoords + 0.3) * 0.0625, trit_textureLODBias).xyzw;
|
|
float altitude = abs((trit_basis * V).z) * trit_invZoom;
|
|
float invBlendDist = 10.0 * trit_invNoiseDistance;
|
|
float amp = 1.0 - min(1.0, altitude * invBlendDist);
|
|
vec4 slopesAndFoam = slopesAndFoamHigh * amp;
|
|
float totalAmp = amp;
|
|
amp = min(0.5, altitude * invBlendDist);
|
|
slopesAndFoam += slopesAndFoamMed * amp;
|
|
totalAmp += amp;
|
|
amp = min(0.5, altitude * invBlendDist * 0.5);
|
|
slopesAndFoam += slopesAndFoamLow * amp;
|
|
totalAmp += amp;
|
|
amp = min(0.5, altitude *invBlendDist * 0.25);
|
|
slopesAndFoam += slopesAndFoamReallyLow * amp;
|
|
totalAmp += amp;
|
|
|
|
slopesAndFoam /= totalAmp;
|
|
#else // HIGHALT
|
|
vec4 slopesAndFoam = texture(trit_slopeFoamMap, texCoords, trit_textureLODBias).xyzw;
|
|
#endif // HIGHALT
|
|
|
|
float fresnelScale = length(slopesAndFoam.xyz);
|
|
|
|
#ifdef DETAIL
|
|
for (int n = 1; n <= NUM_OCTAVES; n++) {
|
|
slopesAndFoam.xyz += texture(trit_slopeFoamMap, texCoords * DETAIL_OCTAVE * n, trit_textureLODBias).xyz * DETAIL_BLEND;
|
|
}
|
|
#endif
|
|
#else
|
|
#ifdef HIGHALT
|
|
vec4 slopesAndFoamHigh = texture2D(trit_slopeFoamMap, texCoords, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamMed = texture2D(trit_slopeFoamMap, (texCoords + 0.1) * 0.25, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamLow = texture2D(trit_slopeFoamMap, (texCoords + 0.7) * 0.125, trit_textureLODBias).xyzw;
|
|
vec4 slopesAndFoamReallyLow = texture2D(trit_slopeFoamMap, (texCoords + 0.3) * 0.0625, trit_textureLODBias).xyzw;
|
|
float altitude = abs((trit_basis * V).z) * trit_invZoom;
|
|
float invBlendDist = 10.0 * trit_invNoiseDistance;
|
|
float amp = 1.0 - min(1.0, altitude * invBlendDist);
|
|
vec4 slopesAndFoam = slopesAndFoamHigh * amp;
|
|
float totalAmp = amp;
|
|
amp = min(0.5, altitude * invBlendDist);
|
|
slopesAndFoam += slopesAndFoamMed * amp;
|
|
totalAmp += amp;
|
|
amp = min(0.5, altitude * invBlendDist * 0.5);
|
|
slopesAndFoam += slopesAndFoamLow * amp;
|
|
totalAmp += amp;
|
|
amp = min(0.5, altitude *invBlendDist * 0.25);
|
|
slopesAndFoam += slopesAndFoamReallyLow * amp;
|
|
totalAmp += amp;
|
|
|
|
slopesAndFoam /= totalAmp;
|
|
#else // HIGHALT
|
|
vec4 slopesAndFoam = texture2D(trit_slopeFoamMap, texCoords, trit_textureLODBias).xyzw;
|
|
#endif // HIGHALT
|
|
|
|
float fresnelScale = length(slopesAndFoam.xyz);
|
|
|
|
#ifdef DETAIL
|
|
for (int n = 1; n <= NUM_OCTAVES; n++) {
|
|
slopesAndFoam.xyz += texture2D(trit_slopeFoamMap, texCoords * DETAIL_OCTAVE * n, trit_textureLODBias).xyz * DETAIL_BLEND;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef LEEWARD_DAMPENING
|
|
slopesAndFoam.xyz = mix(vec3(0.0,0.0,1.0), slopesAndFoam.xyz, leewardDampening);
|
|
slopesAndFoam.w *= leewardDampening;
|
|
#endif
|
|
|
|
#ifdef BREAKING_WAVES
|
|
float breakerFadeLocal = clamp(breakerFade, 0.0, 1.0);
|
|
vec3 realNormal = mix(vec3(0.0,0.0,1.0), slopesAndFoam.xyz, breakerFadeLocal);
|
|
#else
|
|
vec3 realNormal = slopesAndFoam.xyz;
|
|
#endif
|
|
|
|
#ifdef SPARKLE
|
|
float bias = horizDistNorm * horizDistNorm * -64.0;
|
|
bias = mix(bias, -5.0, clamp(altitude * invBlendDist, 0.0, 1.0));
|
|
#ifdef OPENGL32
|
|
vec3 specularSlopes = texture(trit_slopeFoamMap, texCoords, bias).xyz;
|
|
#else
|
|
vec3 specularSlopes = texture2D(trit_slopeFoamMap, texCoords, bias).xyz;
|
|
#endif
|
|
vec3 specNormal = normalize(specularSlopes);
|
|
specNormal = normalize(specNormal.x * localEast + specNormal.y * localNorth + specNormal.z * up);
|
|
#endif
|
|
|
|
vec3 fadedNormal = mix(vec3(0.0,0.0,1.0), realNormal, tileFadeHoriz);
|
|
vec3 N = normalize(fadedNormal + (wakeNormalsAndFoam.xyz - vec3(0.0, 0.0, 1.0)));
|
|
#ifdef OPENGL32
|
|
vec3 unscaledNoise = normalize(texture(trit_noiseTex, noiseTexCoords).xyz - vec3(0.5, 0.5, 0.5));
|
|
#else
|
|
vec3 unscaledNoise = normalize(texture2D(trit_noiseTex, noiseTexCoords).xyz - vec3(0.5, 0.5, 0.5));
|
|
#endif
|
|
vec3 normalNoise = unscaledNoise * trit_noiseAmplitude;
|
|
N += normalNoise;
|
|
|
|
vec3 nNorm = normalize(N.x * localEast + N.y * localNorth + N.z * up);
|
|
|
|
vec3 reflection = reflect(vNorm, nNorm);
|
|
vec3 refraction = refract(vNorm, nNorm, 1.0 / IOR);
|
|
|
|
// We don't need no stinkin Fresnel approximation, do it for real
|
|
#ifdef FAST_FRESNEL
|
|
//float reflectivity = clamp( 0.02+0.97*pow((1.0-dot(reflection, nNorm)),5.0), 0.0, 1.0 );
|
|
|
|
float r=(1.2-1.0)/(1.2+1.0);
|
|
float reflectivity = max(0.0,min(1.0,r+(1.0-r)*pow((1.0-dot(nNorm,reflection)) * fresnelScale, 4.0)));
|
|
|
|
#else
|
|
float cos_theta1 = (dot(vNorm, nNorm));
|
|
float cos_theta2 = (dot(refraction, nNorm));
|
|
|
|
float Fp = (cos_theta1 - (IOR * cos_theta2)) /
|
|
(cos_theta1 + (IOR * cos_theta2));
|
|
float Fs = (cos_theta2 - (IOR * cos_theta1)) /
|
|
(cos_theta2 + (IOR * cos_theta1));
|
|
Fp = Fp * Fp;
|
|
Fs = Fs * Fs;
|
|
|
|
float reflectivity = clamp((Fs + Fp) * 0.5, 0.0, 1.0);
|
|
#endif
|
|
|
|
// No reflections on foam
|
|
float foamClamped = clamp(wakeNormalsAndFoam.w, 0.0, 1.0);
|
|
reflectivity = mix(reflectivity, 0.0, foamClamped);
|
|
|
|
reflectivity *= trit_reflectivityScale;
|
|
|
|
// Prevent reflections from below the horizon
|
|
float amountAbove = min(dot(reflection, up), 0.0);
|
|
reflection += (up * -amountAbove);
|
|
reflection = normalize(reflection);
|
|
|
|
#ifdef OPENGL32
|
|
vec4 envColor = trit_hasEnvMap ? textureLod(trit_cubeMap, trit_cubeMapMatrix * reflection, 0) : vec4(trit_ambientColor, 1.0);
|
|
#else
|
|
vec4 envColor = trit_hasEnvMap ? textureCubeLod(trit_cubeMap, trit_cubeMapMatrix * reflection, 0) : vec4(trit_ambientColor, 1.0);
|
|
#endif
|
|
vec4 reflectedColor = envColor;
|
|
|
|
if( trit_hasPlanarReflectionMap ) {
|
|
// perturb view vector by normal xy coords multiplied by displacement scale
|
|
// normal perturbation represented directly in world oriented space can be computed like this:
|
|
// ( nNorm - dot( nNorm, up ) * up ) == invBasis * vec3( ( trit_basis * nNorm ).xy, 0 )
|
|
vec3 vNormPerturbed = vNorm + ( nNorm - dot( nNorm, up ) * up ) * trit_planarReflectionDisplacementScale;
|
|
vec3 tc = trit_planarReflectionMapMatrix * vNormPerturbed;
|
|
#ifdef OPENGL32
|
|
vec4 planarColor = textureProj( trit_planarReflectionMap, tc );
|
|
#else
|
|
vec2 tcProj = vec2(tc.x / tc.z, tc.y / tc.z);
|
|
vec4 planarColor = texture2D(trit_planarReflectionMap, tcProj);
|
|
#endif
|
|
|
|
//planarColor.a = planarColor.a > 0.9 ? planarColor.a : 0;
|
|
|
|
reflectedColor = mix( envColor, planarColor, planarColor.a * trit_planarReflectionBlend);
|
|
|
|
user_reflection_adjust(envColor, planarColor, trit_planarReflectionBlend, reflectedColor);
|
|
} else {
|
|
user_reflection_adjust(envColor, vec4(0.0,0.0,0.0,0.0), 1.0, reflectedColor);
|
|
}
|
|
|
|
vec3 finalAmbient = trit_ambientColor;
|
|
vec3 finalDiffuse = trit_lightColor * max(0, dot(trit_L, nNorm));
|
|
|
|
vec3 refractedLight, LNorm;
|
|
|
|
if (trit_underwater) {
|
|
LNorm = normalize(trit_L);
|
|
refractedLight = refract(LNorm, up, 1.0 / 1.333);
|
|
nNorm = -nNorm;
|
|
} else {
|
|
refractedLight = LNorm = normalize(trit_L);
|
|
}
|
|
|
|
#ifdef SPARKLE
|
|
vec3 R = reflect(refractedLight, specNormal);
|
|
#else
|
|
vec3 R = reflect(refractedLight, nNorm);
|
|
#endif
|
|
|
|
float S = max(0.0, dot(vNorm, R));
|
|
|
|
#ifndef HDR
|
|
vec3 finalSpecular = trit_lightColor * min(1.0, pow(S, trit_shininess + horizDist * SPECULAR_DISTANCE_FACTOR) * trit_sunIntensity * SPECULAR_BOOST * reflectivity);
|
|
#else
|
|
vec3 finalSpecular = trit_lightColor * pow(S, trit_shininess + horizDist * SPECULAR_DISTANCE_FACTOR) * trit_sunIntensity * SPECULAR_BOOST * reflectivity;
|
|
#endif
|
|
|
|
// Allow lighting overrides in the user-functions.glsl
|
|
user_lighting(trit_L, V, nNorm
|
|
, vVertex_Projection_Space, trit_shininess, finalAmbient, finalDiffuse, finalSpecular);
|
|
|
|
float shadow = user_cloud_shadow_fragment();
|
|
|
|
finalDiffuse *= vec3(shadow);
|
|
|
|
finalSpecular *= vec3(shadow);
|
|
|
|
vec3 Csunlight = finalSpecular;
|
|
|
|
#ifndef HDR
|
|
vec3 Clight = min(finalAmbient + finalDiffuse, 1.0);
|
|
#else
|
|
vec3 Clight = finalAmbient + finalDiffuse;
|
|
#endif
|
|
|
|
vec3 Cskylight = mix(trit_refractColor * Clight, reflectedColor.rgb* vec3(shadow), reflectivity);
|
|
|
|
#ifdef OPENGL32
|
|
vec3 Clightfoam = texture(trit_lightFoamTex, foamTexCoords).xyz;
|
|
Clightfoam += texture(trit_lightFoamTex, foamTexCoords * 1.7).xyz;
|
|
Clightfoam += texture(trit_lightFoamTex, foamTexCoords * 0.3).xyz;
|
|
Clightfoam *= finalAmbient;
|
|
#else
|
|
vec3 Clightfoam = texture2D(trit_lightFoamTex, foamTexCoords).xyz;
|
|
Clightfoam += texture2D(trit_lightFoamTex, foamTexCoords * 1.7).xyz;
|
|
Clightfoam += texture2D(trit_lightFoamTex, foamTexCoords * 0.3).xyz;
|
|
Clightfoam *= finalAmbient;
|
|
#endif
|
|
|
|
vec3 CiNoLight = vec3(0.0,0.0,0.0);
|
|
|
|
#ifdef BREAKING_WAVES
|
|
float foamAmount = (clamp(slopesAndFoam.w, 0.0, 1.0) * breakerFadeLocal);
|
|
foamAmount = foamAmount * foamAmount;
|
|
vec3 foamColor = Clightfoam * foamAmount;
|
|
CiNoLight = (foamColor * tileFadeHoriz * trit_foamBlend);
|
|
|
|
#ifdef OPENGL32
|
|
vec3 breakerTex = texture(trit_breakerTex, breakerTexCoords).xyz;
|
|
#else
|
|
vec3 breakerTex = texture2D(trit_breakerTex, breakerTexCoords).xyz;
|
|
#endif
|
|
|
|
float breakerNoise = max(0.0, (1.0 - abs(unscaledNoise.x * 6.0)));
|
|
CiNoLight += breakerTex * breaker * tileFadeHoriz * breakerNoise;
|
|
#else
|
|
float foamAmount = (clamp(slopesAndFoam.w, 0.0, 1.0));
|
|
foamAmount = foamAmount * foamAmount;
|
|
vec3 foamColor = Clightfoam * foamAmount;
|
|
CiNoLight += (foamColor * tileFadeHoriz * trit_foamBlend);
|
|
#endif
|
|
|
|
CiNoLight += Clightfoam * foamClamped * trit_foamBlend;
|
|
|
|
vec3 Cwash = vec3(0.0,0.0,0.0);
|
|
|
|
#ifdef PROPELLER_WASH
|
|
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
Cwash = applyPropWash(propWashCoords, localPropWashCoords, finalAmbient);
|
|
#else
|
|
finalWashWidth = activeWashWidth;
|
|
|
|
float washTexCoordZClamped = clamp(washTexCoords.z, 0.0, 1.0);
|
|
|
|
#ifdef OPENGL32
|
|
Cwash = texture(trit_washTex, washTexCoords.xy).xyz * finalAmbient * washTexCoordZClamped;
|
|
#else
|
|
Cwash = texture2D(trit_washTex, washTexCoords.xy).xyz * finalAmbient * washTexCoordZClamped;
|
|
#endif
|
|
#endif
|
|
|
|
CiNoLight += Cwash * vec3(shadow);
|
|
#endif
|
|
|
|
float doubleRefraction = max(0.0,dot(-vNorm,nNorm)) * (1.0 - dot(-vNorm, up));
|
|
doubleRefraction += slopesAndFoam.w * BUBBLES;
|
|
doubleRefraction *= tileFade;
|
|
|
|
vec3 Ci = Cskylight + Csunlight + CiNoLight;
|
|
Ci += trit_doubleRefractionColor * Clight * doubleRefraction * trit_doubleRefractionIntensity;
|
|
|
|
float transparencyLocal = clamp(transparency, 0.0, 1.0);
|
|
float alpha = hasHeightMap ? 1.0 - transparencyLocal : mix(1.0 - transparencyLocal, 1.0, reflectivity);
|
|
vec4 waterColor = vec4(Ci, alpha);
|
|
vec4 fogColor4 = vec4(trit_fogColor, hasHeightMap ? alpha : 1.0);
|
|
|
|
float fogBlend = clamp(fogFactor, 0.0, 1.0);
|
|
|
|
// Allow user override of fog in user-functions.glsl
|
|
user_fog(V, waterColor, fogColor4, fogBlend);
|
|
|
|
vec4 finalColor = mix(fogColor4, waterColor, fogBlend);
|
|
|
|
finalColor.xyz = pow(finalColor.xyz, vec3(trit_oneOverGamma, trit_oneOverGamma, trit_oneOverGamma));
|
|
|
|
#ifndef HDR
|
|
vec4 toneMappedColor = clamp(finalColor, 0.0, 1.0);
|
|
#else
|
|
vec4 toneMappedColor = finalColor;
|
|
#endif
|
|
|
|
toneMappedColor.w *= trit_transparency;
|
|
|
|
user_tonemap(finalColor, toneMappedColor);
|
|
|
|
vec3 Cdiffuse = vec3(0.0,0.0,0.0);
|
|
user_diffuse_color( Cdiffuse, CiNoLight, Cwash, reflectedColor, reflectivity, nNorm );
|
|
|
|
writeFragmentData(toneMappedColor, vec4( Cdiffuse, alpha ), trit_lightColor, nNorm);
|
|
|
|
}
|