541 lines
18 KiB
GLSL
541 lines
18 KiB
GLSL
// ocean-frag-flat-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 wakeSlopeAndFoam;
|
|
#ifdef PROPELLER_WASH
|
|
in vec3 washTexCoords;
|
|
in float activeWashWidth;
|
|
#endif
|
|
in float fogFactor;
|
|
in float transparency;
|
|
in float depth;
|
|
#ifdef BREAKING_WAVES
|
|
in float breaker;
|
|
in float breakerFade;
|
|
in vec2 breakerTexCoords;
|
|
#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 propWashCoord;
|
|
#endif
|
|
#else
|
|
varying vec3 V;
|
|
varying vec2 foamTexCoords;
|
|
varying vec2 texCoords;
|
|
varying vec2 noiseTexCoords;
|
|
varying vec3 wakeSlopeAndFoam;
|
|
#ifdef PROPELLER_WASH
|
|
varying vec3 washTexCoords;
|
|
varying float activeWashWidth;
|
|
#endif
|
|
varying float fogFactor;
|
|
varying float transparency;
|
|
varying float depth;
|
|
#ifdef BREAKING_WAVES
|
|
varying float breaker;
|
|
varying float breakerFade;
|
|
varying vec2 breakerTexCoords;
|
|
#endif
|
|
#ifdef LEEWARD_DAMPENING
|
|
varying float leewardDampening;
|
|
#endif
|
|
varying vec4 vVertex_Eye_Space;
|
|
varying vec4 vVertex_Projection_Space;
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
varying vec3 propWashCoord;
|
|
#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 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 (washes[i].distFromSource == 0) continue;
|
|
|
|
vec3 C = trit_washes[i].deltaPos;
|
|
vec3 A = v - 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) {
|
|
vec3 up = vec3(0.0,0.0,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 rr = (-depth / 100.0) + 0.5;
|
|
rr = clamp(rr, 0.0, 1.0);
|
|
gl_FragColor = vec4(rr, rr, rr, 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.33333;
|
|
|
|
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);
|
|
#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 * trit_invZoom;
|
|
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 // DETAIL
|
|
vec3 unscaledNoise = normalize( texture(trit_noiseTex, noiseTexCoords).xyz - vec3(0.5, 0.5, 0.5) );
|
|
#else // OPENGL32
|
|
|
|
#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 * trit_invZoom;
|
|
|
|
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
|
|
// Uncomment to visualize Jacobian
|
|
//gl_FragColor = vec4(slopesAndFoam.z, slopesAndFoam.z, slopesAndFoam.z, 1.0);
|
|
//return;
|
|
|
|
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 // DETAIL
|
|
vec3 unscaledNoise = normalize(texture2D(trit_noiseTex, noiseTexCoords).xyz - vec3(0.5, 0.5, 0.5) );
|
|
#endif // else OPENGL32
|
|
|
|
vec3 normalNoise = unscaledNoise * trit_noiseAmplitude;
|
|
normalNoise.z = abs( normalNoise.z );
|
|
|
|
slopesAndFoam.xyz = normalize(slopesAndFoam.xyz);
|
|
vec4 finalSlopesAndFoam = slopesAndFoam;
|
|
#ifdef LEEWARD_DAMPENING
|
|
finalSlopesAndFoam.xyz = mix(vec3(0.0,0.0,1.0), finalSlopesAndFoam.xyz, leewardDampening);
|
|
finalSlopesAndFoam.w *= leewardDampening;
|
|
#endif
|
|
|
|
vec3 wakeSlopeAndFoamClamped = clamp(wakeSlopeAndFoam.xyz, 0.0,1.0);
|
|
vec3 wx = vec3(1.0, 0.0, wakeSlopeAndFoamClamped.x);
|
|
vec3 wy = vec3(0.0, 1.0, wakeSlopeAndFoamClamped.y);
|
|
vec3 wakeNormal = normalize(cross(wx, wy));
|
|
|
|
#ifdef BREAKING_WAVES
|
|
float breakerFadeLocal = clamp(breakerFade, 0.0, 1.0);
|
|
vec3 realNormal = mix(vec3(0.0,0.0,1.0), finalSlopesAndFoam.xyz, breakerFadeLocal);
|
|
#else
|
|
vec3 realNormal = finalSlopesAndFoam.xyz;
|
|
#endif
|
|
realNormal = normalize(realNormal + wakeNormal);
|
|
|
|
#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 = trit_invBasis * normalize(specularSlopes);
|
|
#endif
|
|
|
|
vec3 fadedNormal = mix(vec3(0.0,0.0,1.0), realNormal, tileFadeHoriz);
|
|
|
|
vec3 nNorm = trit_invBasis * normalize(fadedNormal + (normalNoise * (1.0 - tileFade)));
|
|
|
|
vec3 P = reflect(vNorm, nNorm);
|
|
|
|
#if 0
|
|
float reflectionHalfSphere = dot( P, trit_invBasis[2] /* == trit_invBasis * vec3(0,0,1) */ );
|
|
|
|
if( reflectionHalfSphere < 0. ) { // make secondary reflection if reflected vector points down
|
|
P = reflect(P, nNorm);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FAST_FRESNEL
|
|
//float reflectivity = clamp( 0.02+0.97*pow((1.0-dot(P, 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,P)) * fresnelScale, 4.0)));
|
|
|
|
#else
|
|
vec3 S = refract(P, nNorm, 1.0 / IOR);
|
|
|
|
float cos_theta1 = (dot(P, nNorm));
|
|
float cos_theta2 = (dot(S, -nNorm));
|
|
|
|
float Fp = (cos_theta1 - (IOR * cos_theta2)) /
|
|
((IOR * cos_theta2) + cos_theta1);
|
|
float Fs = (cos_theta2 - (IOR * cos_theta1)) /
|
|
((IOR * cos_theta1) + cos_theta2);
|
|
Fp = Fp * Fp;
|
|
Fs = Fs * Fs;
|
|
|
|
float reflectivity = clamp((Fs + Fp) * 0.5, 0.0, 1.0);
|
|
#endif
|
|
|
|
// No reflections on foam.
|
|
reflectivity = mix(reflectivity, 0.0, clamp(wakeSlopeAndFoam.z, 0.0, 1.0));
|
|
|
|
reflectivity *= trit_reflectivityScale;
|
|
|
|
vec4 envColor;
|
|
|
|
if (trit_hasEnvMap) {
|
|
P = trit_basis * P;
|
|
P.z = max(0, P.z);
|
|
P = trit_invBasis * normalize(P);
|
|
|
|
#ifdef OPENGL32
|
|
envColor = textureLod(trit_cubeMap, trit_cubeMapMatrix * P, 0);
|
|
#else
|
|
envColor = textureCubeLod(trit_cubeMap, trit_cubeMapMatrix * P, 0);
|
|
#endif
|
|
} else {
|
|
envColor = vec4(trit_ambientColor, 1.0);
|
|
}
|
|
|
|
vec4 reflectedColor = envColor;
|
|
|
|
if( trit_hasPlanarReflectionMap ) {
|
|
vec3 up = trit_invBasis[2]; // == trit_invBasis * vec3( 0.0, 0.0, 1.0 )
|
|
// perturb view vector by normal xy coords multiplied by displacement scale
|
|
// when we do it in world oriented space this perturbation is equal to:
|
|
// ( nNorm - dot( nNorm, up ) * up ) == trit_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.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);
|
|
}
|
|
|
|
// This makes the water more visually interesting. For realism, comment out.
|
|
//reflectivity = pow(reflectivity, 0.8);
|
|
|
|
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, trit_invBasis[2], 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 spec = max(0.0, dot(vNorm, R));
|
|
|
|
#ifndef HDR
|
|
vec3 finalSpecular = trit_lightColor * min(1.0, pow(spec, trit_shininess + horizDist * SPECULAR_DISTANCE_FACTOR) * trit_sunIntensity * SPECULAR_BOOST * reflectivity);
|
|
#else
|
|
vec3 finalSpecular = trit_lightColor * pow(spec, 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);
|
|
|
|
// Fade out foam with distance to hide tiling
|
|
#ifdef BREAKING_WAVES
|
|
float foamAmount = clamp(finalSlopesAndFoam.w, 0.0, 1.0) * breakerFadeLocal;
|
|
foamAmount = foamAmount * foamAmount;
|
|
vec3 foamColor = Clightfoam * foamAmount;
|
|
|
|
|
|
#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(finalSlopesAndFoam.w, 0.0, 1.0));
|
|
foamAmount = foamAmount * foamAmount;
|
|
vec3 foamColor = Clightfoam * foamAmount;
|
|
#endif
|
|
|
|
CiNoLight += (foamColor * tileFadeHoriz * trit_foamBlend);
|
|
CiNoLight += Clightfoam * wakeSlopeAndFoamClamped.z * trit_foamBlend;
|
|
|
|
vec3 Cwash = vec3(0.0,0.0,0.0);
|
|
|
|
#ifdef PROPELLER_WASH
|
|
|
|
#ifdef PER_FRAGMENT_PROP_WASH
|
|
Cwash = applyPropWash(propWashCoord, 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, trit_invBasis[2]));
|
|
doubleRefraction += finalSlopesAndFoam.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
|
|
|
|
user_tonemap(finalColor, toneMappedColor);
|
|
|
|
toneMappedColor.w *= trit_transparency;
|
|
|
|
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);
|
|
|
|
}
|