Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/shaders/glsl/water_high.fs
Show First 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | vec3 get_fog(vec3 color) | ||||
fogFactor = fogFactor * (1.0 - maxFog) + maxFog; | fogFactor = fogFactor * (1.0 - maxFog) + maxFog; | ||||
fogFactor = clamp(fogFactor, 0.0, 1.0); | fogFactor = clamp(fogFactor, 0.0, 1.0); | ||||
return mix(fogColor, color, fogFactor); | return mix(fogColor, color, fogFactor); | ||||
} | } | ||||
vec4 getReflection(vec3 normal) | vec3 getNormal() | ||||
{ | |||||
float wavyEffect = waveParams1.r; | |||||
float baseScale = waveParams1.g; | |||||
float flattenism = waveParams1.b; | |||||
float baseBump = waveParams1.a; | |||||
float BigMovement = waveParams2.b; | |||||
// This method uses 60 animated water frames. We're blending between each two frames | |||||
// Scale the normal textures by waviness so that big waviness means bigger waves. | |||||
vec3 ww1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy; | |||||
vec3 ww2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy; | |||||
vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5); | |||||
ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y; | |||||
ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x; | |||||
ww1.y = wwInterp.y; | |||||
// Flatten them based on waviness. | |||||
vec3 normal = normalize(mix(vec3(0.0, 1.0, 0.0), ww1, clamp(baseBump + fwaviness / flattenism, 0.0, 1.0))); | |||||
#if USE_FANCY_EFFECTS | |||||
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize); | |||||
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | |||||
normal.xz = mix(normal.xz, fancyeffects.rb, fancyeffects.a / 2.0); | |||||
#else | |||||
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | |||||
#endif | |||||
normal = vec3(-normal.x, normal.y, -normal.z); // The final wave normal vector. | |||||
Silier: this could go to return statement :) | |||||
vladislavbelovAuthorUnsubmitted Done Inline ActionsYep. vladislavbelov: Yep. | |||||
return normal; | |||||
} | |||||
vec3 getSpecular(vec3 normal, vec3 eyeVec) | |||||
{ | |||||
// Specular lighting vectors | |||||
vec3 specularVector = reflect(sunDir, normal); | |||||
// pow is undefined for null or negative values, except on intel it seems. | |||||
float specularIntensity = pow(max(dot(specularVector, eyeVec), 0.0), 100.0); | |||||
// Workaround to fix too flattened water. | |||||
specularIntensity = smoothstep(0.6, 1.0, specularIntensity); | |||||
return clamp(specularIntensity * sunColor, 0.0, 1.0); | |||||
} | |||||
vec4 getReflection(vec3 normal, vec3 eyeVec) | |||||
{ | { | ||||
// Reflections | // Reflections | ||||
// 3 level of settings: | // 3 level of settings: | ||||
// -If a player has refraction and reflection disabled, we return a gradient of blue based on the Y component. | // -If a player has refraction and reflection disabled, we return a gradient of blue based on the Y component. | ||||
// -If a player has refraction OR reflection, we return a reflection of the actual skybox used. | // -If a player has refraction OR reflection, we return a reflection of the actual skybox used. | ||||
// -If a player has reflection enabled, we also return a reflection of actual entities where applicable. | // -If a player has reflection enabled, we also return a reflection of actual entities where applicable. | ||||
// reflMod reduces the intensity of reflections somewhat since they kind of wash refractions out otherwise. | // reflMod reduces the intensity of reflections somewhat since they kind of wash refractions out otherwise. | ||||
float reflMod = 0.75; | float reflMod = 0.75; | ||||
vec3 eye = reflect(v_eyeVec, normal); | vec3 eye = reflect(eyeVec, normal); | ||||
#if USE_REFLECTION | #if USE_REFLECTION | ||||
float refVY = clamp(v_eyeVec.y * 2.0, 0.05, 1.0); | float refVY = clamp(eyeVec.y * 2.0, 0.05, 1.0); | ||||
// Distort the reflection coords based on waves. | // Distort the reflection coords based on waves. | ||||
vec2 reflCoords = (0.5 * reflectionCoords.xy - 15.0 * normal.zx / refVY) / reflectionCoords.z + 0.5; | vec2 reflCoords = (0.5 * reflectionCoords.xy - 15.0 * normal.zx / refVY) / reflectionCoords.z + 0.5; | ||||
vec4 refTex = texture2D(reflectionMap, reflCoords); | vec4 refTex = texture2D(reflectionMap, reflCoords); | ||||
vec3 reflColor = refTex.rgb; | vec3 reflColor = refTex.rgb; | ||||
// Interpolate between the sky color and nearby objects. | // Interpolate between the sky color and nearby objects. | ||||
// Only do this when alpha is rather low, or transparent leaves show up as extremely white. | // Only do this when alpha is rather low, or transparent leaves show up as extremely white. | ||||
if (refTex.a < 0.4) | if (refTex.a < 0.4) | ||||
reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a); | reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a); | ||||
// Let actual objects be reflected fully. | // Let actual objects be reflected fully. | ||||
reflMod = max(refTex.a, 0.75); | reflMod = max(refTex.a, 0.75); | ||||
#elif USE_REFRACTION | #elif USE_REFRACTION | ||||
vec3 reflColor = textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb; | vec3 reflColor = textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb; | ||||
#else // !USE_REFLECTION && !USE_REFRACTION | #else // !USE_REFLECTION && !USE_REFRACTION | ||||
// Simplest case for reflection, return a gradient of blue based on Y component. | // Simplest case for reflection, return a gradient of blue based on Y component. | ||||
vec3 reflColor = mix(vec3(0.76, 0.84, 0.92), vec3(0.24, 0.43, 0.71), -eye.y); | vec3 reflColor = mix(vec3(0.76, 0.84, 0.92), vec3(0.24, 0.43, 0.71), -eye.y); | ||||
#endif | #endif | ||||
return vec4(reflColor, reflMod); | return vec4(reflColor, reflMod); | ||||
} | } | ||||
vec4 getRefraction(vec3 normal, float depthLimit) | vec4 getRefraction(vec3 normal, vec3 eyeVec, float depthLimit) | ||||
{ | { | ||||
float depth; | float depth; | ||||
#if USE_REAL_DEPTH | #if USE_REAL_DEPTH | ||||
// Compute real depth at the target point. | // Compute real depth at the target point. | ||||
float water_b = gl_FragCoord.z; | float water_b = gl_FragCoord.z; | ||||
float water_n = 2.0 * water_b - 1.0; | float water_n = 2.0 * water_b - 1.0; | ||||
float waterDBuffer = 2.0 * zNear * zFar / (zFar + zNear - water_n * (zFar - zNear)); | float waterDBuffer = 2.0 * zNear * zFar / (zFar + zNear - water_n * (zFar - zNear)); | ||||
float undisto_z_b = texture2D(depthTex, (gl_FragCoord.xy) / screenSize).x; | float undisto_z_b = texture2D(depthTex, (gl_FragCoord.xy) / screenSize).x; | ||||
float undisto_z_n = 2.0 * undisto_z_b - 1.0; | float undisto_z_n = 2.0 * undisto_z_b - 1.0; | ||||
float waterDepth_undistorted = (2.0 * zNear * zFar / (zFar + zNear - undisto_z_n * (zFar - zNear)) - waterDBuffer); | float waterDepth_undistorted = (2.0 * zNear * zFar / (zFar + zNear - undisto_z_n * (zFar - zNear)) - waterDBuffer); | ||||
// Set depth to the depth at the undistorted point. | // Set depth to the depth at the undistorted point. | ||||
depth = waterDepth_undistorted; | depth = waterDepth_undistorted; | ||||
#else | #else | ||||
// fake depth computation: take the value at the vertex, add some if we are looking at a more oblique angle. | // fake depth computation: take the value at the vertex, add some if we are looking at a more oblique angle. | ||||
depth = waterDepth / (min(0.5, v_eyeVec.y) * 1.5 * min(0.5, v_eyeVec.y) * 2.0); | depth = waterDepth / (min(0.5, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0); | ||||
#endif | #endif | ||||
#if USE_REFRACTION | #if USE_REFRACTION | ||||
// for refraction we want to distort more as depth goes down. | // for refraction we want to distort more as depth goes down. | ||||
// 1) compute a distortion based on depth at the pixel. | // 1) compute a distortion based on depth at the pixel. | ||||
// 2) Re-sample the depth at the target point | // 2) Re-sample the depth at the target point | ||||
// 3) Sample refraction texture | // 3) Sample refraction texture | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
depth = max(depth, depthLimit); | depth = max(depth, depthLimit); | ||||
#endif | #endif | ||||
vec3 refColor = color; | vec3 refColor = color; | ||||
#endif | #endif | ||||
// for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides". | // for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides". | ||||
// And it looks weird (again, we are not used to seeing water from above). | // And it looks weird (again, we are not used to seeing water from above). | ||||
float fixedVy = max(v_eyeVec.y, 0.01); | float fixedVy = max(eyeVec.y, 0.01); | ||||
float murky = mix(200.0, 0.1, pow(murkiness, 0.25)); | float murky = mix(200.0, 0.1, pow(murkiness, 0.25)); | ||||
// Apply water tint and murk color. | // Apply water tint and murk color. | ||||
float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); | float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); | ||||
float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); | float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); | ||||
vec3 colll = mix(refColor * tint, refColor, ColextFact); | vec3 colll = mix(refColor * tint, refColor, ColextFact); | ||||
vec3 refrColor = mix(color, colll, extFact); | vec3 refrColor = mix(color, colll, extFact); | ||||
float alpha = clamp(depth, 0.0, 1.0); | float alpha = clamp(depth, 0.0, 1.0); | ||||
#if !USE_REFRACTION | #if !USE_REFRACTION | ||||
alpha = (1.4 - extFact) * alpha; | alpha = (1.4 - extFact) * alpha; | ||||
#endif | #endif | ||||
return vec4(refrColor, alpha); | return vec4(refrColor, alpha); | ||||
} | } | ||||
void main() | void main() | ||||
{ | { | ||||
// Calculate water normals. | vec3 eyeVec = normalize(v_eyeVec); | ||||
vec3 normal = getNormal(); | |||||
float wavyEffect = waveParams1.r; | |||||
float baseScale = waveParams1.g; | |||||
float flattenism = waveParams1.b; | |||||
float baseBump = waveParams1.a; | |||||
float BigMovement = waveParams2.b; | |||||
// This method uses 60 animated water frames. We're blending between each two frames | |||||
// Scale the normal textures by waviness so that big waviness means bigger waves. | |||||
vec3 ww1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy; | |||||
vec3 ww2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy; | |||||
vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5); | |||||
ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y; | |||||
ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x; | |||||
ww1.y = wwInterp.y; | |||||
// Flatten them based on waviness. | |||||
vec3 normal = normalize(mix(vec3(0.0, 1.0, 0.0), ww1, clamp(baseBump + fwaviness / flattenism, 0.0, 1.0))); | |||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize); | vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize); | ||||
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | vec4 refrColor = getRefraction(normal, eyeVec, fancyeffects.a); | ||||
normal.xz = mix(normal.xz, fancyeffects.rb, fancyeffects.a / 2.0); | |||||
#else | #else | ||||
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | vec4 refrColor = getRefraction(normal, eyeVec, 0.0); | ||||
#endif | #endif | ||||
normal = vec3(-normal.x, normal.y, -normal.z); // The final wave normal vector. | vec4 reflColor = getReflection(normal, eyeVec); | ||||
#if USE_FANCY_EFFECTS | |||||
vec4 refrColor = getRefraction(normal, fancyeffects.a); | |||||
#else | |||||
vec4 refrColor = getRefraction(normal, 0.0); | |||||
#endif | |||||
vec4 reflColor = getReflection(normal); | |||||
// How perpendicular to the normal our view is. Used for fresnel. | // How perpendicular to the normal our view is. Used for fresnel. | ||||
float ndotv = clamp(dot(normal, v_eyeVec), 0.0, 1.0); | float ndotv = clamp(dot(normal, eyeVec), 0.0, 1.0); | ||||
// Fresnel for "how much reflection vs how much refraction". | // Fresnel for "how much reflection vs how much refraction". | ||||
float fresnel = clamp(((pow(1.1 - ndotv, 2.0)) * 1.5), 0.1, 0.75); // Approximation. I'm using 1.1 and not 1.0 because it causes artifacts, see #1714 | float fresnel = clamp(((pow(1.1 - ndotv, 2.0)) * 1.5), 0.1, 0.75); // Approximation. I'm using 1.1 and not 1.0 because it causes artifacts, see #1714 | ||||
// Specular lighting vectors | vec3 specular = getSpecular(normal, eyeVec); | ||||
vec3 specVector = reflect(sunDir, ww1); | |||||
// pow is undefined for null or negative values, except on intel it seems. | |||||
float specIntensity = clamp(pow(abs(dot(specVector, v_eyeVec)), 100.0), 0.0, 1.0); | |||||
vec3 specular = specIntensity * 1.2 * mix(vec3(1.5), sunColor, 0.5); | |||||
vec3 color; | vec3 color; | ||||
#if USE_SHADOWS_ON_WATER && USE_SHADOW | #if USE_SHADOWS_ON_WATER && USE_SHADOW | ||||
float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw)); | float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw)); | ||||
float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2); | float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2); | ||||
color = mix(refrColor.rgb, reflColor.rgb, fresShadow * reflColor.a); | color = mix(refrColor.rgb, reflColor.rgb, fresShadow * reflColor.a); | ||||
color += shadow * specular; | color += shadow * specular; | ||||
#else | #else | ||||
color = mix(refrColor.rgb, reflColor.rgb, fresnel * reflColor.a); | color = mix(refrColor.rgb, reflColor.rgb, fresnel * reflColor.a); | ||||
color += specular; | color += specular; | ||||
#endif | #endif | ||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
float wavyEffect = waveParams1.r; | |||||
float baseScale = waveParams1.g; | |||||
float BigMovement = waveParams2.b; | |||||
vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; | vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; | ||||
vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; | vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; | ||||
vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; | vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; | ||||
vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; | vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; | ||||
vec3 foaminterp = mix(foam1, foam2, moddedTime); | vec3 foaminterp = mix(foam1, foam2, moddedTime); | ||||
foaminterp *= mix(foam3, foam4, moddedTime); | foaminterp *= mix(foam3, foam4, moddedTime); | ||||
foam1.x = abs(foaminterp.x * WindCosSin.x) + abs(foaminterp.z * WindCosSin.y); | foam1.x = abs(foaminterp.x * WindCosSin.x) + abs(foaminterp.z * WindCosSin.y); | ||||
color += fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5); | color += fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5); | ||||
#endif | #endif | ||||
#if USE_FOG | #if USE_FOG | ||||
color = get_fog(color); | color = get_fog(color); | ||||
#endif | #endif | ||||
float alpha = refrColor.a; | float alpha = refrColor.a; | ||||
float losMod = texture2D(losMap, losCoords.st).a; | float losMod = texture2D(losMap, losCoords.st).a; | ||||
losMod = losMod < 0.03 ? 0.0 : losMod; | losMod = losMod < 0.03 ? 0.0 : losMod; | ||||
gl_FragColor = vec4(color * losMod, alpha); | gl_FragColor = vec4(color * losMod, alpha); | ||||
} | } |
Wildfire Games · Phabricator
this could go to return statement :)