Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/shaders/glsl/water_high.fs
#version 110 | #version 110 | ||||
vladislavbelov: Space. | |||||
#include "common/fog.h" | #include "common/fog.h" | ||||
#include "common/los_fragment.h" | #include "common/los_fragment.h" | ||||
#include "common/shadows_fragment.h" | #include "common/shadows_fragment.h" | ||||
// Environment settings | // Environment settings | ||||
uniform vec3 ambient; | uniform vec3 ambient; | ||||
uniform vec3 sunDir; | uniform vec3 sunDir; | ||||
uniform vec3 sunColor; | uniform vec3 sunColor; | ||||
uniform mat4 skyBoxRot; | uniform mat4 skyBoxRot; | ||||
uniform vec3 cameraPos; | uniform vec3 cameraPos; | ||||
uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture | uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture | ||||
uniform vec3 color; // color of the water | uniform vec3 color; // color of the water | ||||
uniform vec3 tint; // Tint for refraction (used to simulate particles in water) | uniform vec3 tint; // Tint for refraction (used to simulate particles in water) | ||||
uniform float murkiness; // Amount of tint to blend in with the refracted color | uniform float murkiness; // Amount of tint to blend in with the refracted color | ||||
Not Done Inline ActionsI'd like to avoid the alignment at all, since every change breaks blame. vladislavbelov: I'd like to avoid the alignment at all, since every change breaks blame. | |||||
uniform float windAngle; | uniform float windAngle; | ||||
varying vec2 WindCosSin; | varying vec2 WindCosSin; | ||||
uniform vec2 screenSize; | uniform vec2 screenSize; | ||||
varying float moddedTime; | varying float moddedTime; | ||||
varying vec3 worldPos; | varying vec3 worldPos; | ||||
varying float waterDepth; | varying float waterDepth; | ||||
varying vec2 waterInfo; | varying vec2 waterInfo; | ||||
varying vec3 v_eyeVec; | varying vec3 v_eyeVec; | ||||
varying vec4 normalCoords; | varying vec4 normalCoords; | ||||
#if USE_REFLECTION | #if USE_REFLECTION | ||||
varying vec3 reflectionCoords; | varying vec3 reflectionCoords; | ||||
#endif | #endif | ||||
#if USE_REFRACTION | #if USE_REFRACTION | ||||
varying vec3 refractionCoords; | varying vec3 refractionCoords; | ||||
#endif | #endif | ||||
varying float fwaviness; | varying float fwaviness; | ||||
varying float sun_dimming_factor; | |||||
uniform samplerCube skyCube; | uniform samplerCube skyCube; | ||||
uniform sampler2D normalMap; | uniform sampler2D normalMap; | ||||
uniform sampler2D normalMap2; | uniform sampler2D normalMap2; | ||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
uniform sampler2D waterEffectsTex; | uniform sampler2D waterEffectsTex; | ||||
#endif | #endif | ||||
uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump | uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump | ||||
uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement | uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement | ||||
#if USE_REFLECTION | #if USE_REFLECTION | ||||
uniform sampler2D reflectionMap; | uniform sampler2D reflectionMap; | ||||
#endif | #endif | ||||
#if USE_REFRACTION | #if USE_REFRACTION | ||||
uniform sampler2D refractionMap; | uniform sampler2D refractionMap; | ||||
#if USE_REAL_DEPTH | #if USE_REAL_DEPTH | ||||
uniform sampler2D depthTex; | uniform sampler2D depthTex; | ||||
uniform mat4 projInvTransform; | uniform mat4 projInvTransform; | ||||
uniform mat4 viewInvTransform; | uniform mat4 viewInvTransform; | ||||
#endif | #endif | ||||
#endif | #endif | ||||
vec3 getNormal(vec4 fancyeffects) | |||||
const float tide = 1.7; // Yards; controls how wide the wet coast look extends | |||||
const float water_specular_power = 33.3; | |||||
const float dispersion_factor = 0.5 / ( 1.0 - pow(0.5, (1.0 / water_specular_power)) ); | |||||
const float reflection_distort = 3.3; // Controls distortion of reflecte objects (not sky). | |||||
const float IOR_mul = 1.1; // Visual adjustment (hack). | |||||
const vec3 sea_water_refractive_indices_at_15c = vec3( 1.350, 1.344, 1.336 ) * vec3(IOR_mul); | |||||
const vec3 frs_water_refractive_indices_at_15c = vec3( 1.344, 1.338, 1.331 ) * vec3(IOR_mul); | |||||
//from: http://research.engr.oregonstate.edu/parrish/index-refraction-seawater-and-freshwater-function-wavelength-and-temperature | |||||
const vec3 WHITE = vec3(1.0); | |||||
const vec3 wetness_RGB = vec3(0.4,0.45,0.42); | |||||
const float wave_mul = 4.7; | |||||
float LOD_bias_from_spec_power_for_512( float spec_pwr ) | |||||
{ | |||||
return clamp( 7.0 - ( 0.5 * log2(spec_pwr) ), 0.1, 6.9 ); | |||||
} | |||||
vec3 getNormalSub(vec4 fancyeffects, float rescale, float rotate) | |||||
{ | { | ||||
float wavyEffect = waveParams1.r; | float wavyEffect = waveParams1.r; | ||||
float baseScale = waveParams1.g; | float baseScale = waveParams1.g * rescale; | ||||
float flattenism = waveParams1.b; | float flattenism = waveParams1.b; | ||||
float baseBump = waveParams1.a; | float baseBump = waveParams1.a; | ||||
float BigMovement = waveParams2.b; | float BigMovement = waveParams2.b; | ||||
vec4 switchedCoords = mix( normalCoords.xyzw, normalCoords.yxwz, rotate ); | |||||
// This method uses 60 animated water frames. We're blending between each two frames | // 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. | // 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 ww1 = texture2D(normalMap, (switchedCoords.xy + switchedCoords.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 ww2 = texture2D(normalMap2, (switchedCoords.xy + switchedCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy; | ||||
vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5); | vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5); | ||||
ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y; | ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y; | ||||
ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x; | ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x; | ||||
ww1.y = wwInterp.y; | ww1.y = wwInterp.y; | ||||
// Flatten them based on waviness. | // 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))); | 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 | ||||
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | 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); | 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); | normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0); | ||||
#endif | #endif | ||||
return vec3(-normal.x, normal.y, -normal.z); | return normalize( vec3(-normal.x, normal.y, -normal.z) * vec3( wave_mul, 1.0, wave_mul ) ); | ||||
} | |||||
vec3 getNormal(vec4 fancyeffects) | |||||
{ | |||||
vec3 result = vec3(0.0, 1.0, 0.0); | |||||
result = result + vec3(1.0) * getNormalSub(fancyeffects,1.0,0.0); | |||||
//result = result + vec3(0.7) * getNormalSub(fancyeffects,1.382,1.0); | |||||
//result = result + vec3(0.5) * getNormalSub(fancyeffects,0.618,0.0); | |||||
Not Done Inline ActionsUnused code. vladislavbelov: Unused code. | |||||
return normalize(result); | |||||
} | |||||
float sunReflIntensity( vec3 normal ) | |||||
{ | |||||
vec3 half_vec = normalize( normalize(-v_eyeVec) + normalize(sunDir) ); | |||||
float phong_factor = pow( clamp(dot(normal, half_vec), 0.0, 1.0 ), water_specular_power ); | |||||
return phong_factor * dispersion_factor * getShadow(); // This is the sun reflecting; shadows matter! | |||||
} | } | ||||
vec3 getSpecular(vec3 normal, vec3 eyeVec) | vec3 getSpecularSunlight(vec3 normal, vec3 eyeVec) | ||||
{ | { | ||||
// Specular lighting vectors | return sunColor * vec3(sunReflIntensity(normal)); | ||||
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) * 1.2; | |||||
return clamp(specularIntensity * sunColor, 0.0, 1.0); | |||||
} | } | ||||
vec4 getReflection(vec3 normal, vec3 eyeVec) | vec3 getReflections(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. | |||||
float reflMod = 0.75; | |||||
vec3 eye = reflect(eyeVec, normal); | vec3 eye = reflect(eyeVec, normal); | ||||
#if USE_REFLECTION | #if USE_REFLECTION | ||||
float refVY = clamp(eyeVec.y * 2.0, 0.05, 1.0); | float refVY = clamp(eyeVec.y * 2.0, 0.01, 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 - vec2(reflection_distort)*normal.zx / refVY) / reflectionCoords.z + 0.5; | ||||
vec4 refTex = texture2D(reflectionMap, reflCoords); | vec4 refTex = texture2D(reflectionMap, reflCoords); | ||||
float LOD_bias = LOD_bias_from_spec_power_for_512( water_specular_power ); | |||||
vec3 reflColor = refTex.rgb; | vec3 skyColor = textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz, LOD_bias).rgb; | ||||
vec3 reflColor = mix( skyColor, refTex.rgb, refTex.a ); | |||||
// Interpolate between the sky color and nearby objects. | |||||
// Only do this when alpha is rather low, or transparent leaves show up as extremely white. | |||||
if (refTex.a < 0.4) | |||||
reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a); | |||||
// Let actual objects be reflected fully. | |||||
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 reflColor; | ||||
} | } | ||||
#if USE_REFRACTION && USE_REAL_DEPTH | #if USE_REFRACTION && USE_REAL_DEPTH | ||||
vec3 getWorldPositionFromRefractionDepth(vec2 uv) | vec3 getWorldPositionFromRefractionDepth(vec2 uv) | ||||
{ | { | ||||
float depth = texture2D(depthTex, uv).x; | float depth = texture2D(depthTex, uv).x; | ||||
vec4 viewPosition = projInvTransform * (vec4((uv - vec2(0.5)) * 2.0, depth * 2.0 - 1.0, 1.0)); | vec4 viewPosition = projInvTransform * (vec4((uv - vec2(0.5)) * 2.0, depth * 2.0 - 1.0, 1.0)); | ||||
viewPosition /= viewPosition.w; | viewPosition /= viewPosition.w; | ||||
vec3 refrWorldPos = (viewInvTransform * viewPosition).xyz; | vec3 refrWorldPos = (viewInvTransform * viewPosition).xyz; | ||||
// Depth buffer precision errors can give heights above the water. | // Depth buffer precision errors can give heights above the water. | ||||
refrWorldPos.y = min(refrWorldPos.y, worldPos.y); | refrWorldPos.y = min(refrWorldPos.y, worldPos.y); | ||||
return refrWorldPos; | return refrWorldPos; | ||||
} | } | ||||
#endif | #endif | ||||
vec4 getRefraction(vec3 normal, vec3 eyeVec, float depthLimit) | vec4 getRefractedColor(vec3 normal, vec3 eyeVec, float depthLimit) | ||||
{ | { | ||||
#if USE_REFRACTION && USE_REAL_DEPTH | #if USE_REFRACTION && USE_REAL_DEPTH | ||||
// Compute real depth at the target point. | // Compute real depth at the target point. | ||||
vec2 coords = (0.5 * refractionCoords.xy) / refractionCoords.z + 0.5; | vec2 coords = (0.5 * refractionCoords.xy) / refractionCoords.z + 0.5; | ||||
vec3 refrWorldPos = getWorldPositionFromRefractionDepth(coords); | vec3 refrWorldPos = getWorldPositionFromRefractionDepth(coords); | ||||
// Set depth to the depth at the undistorted point. | // Set depth to the depth at the undistorted point. | ||||
float depth = distance(refrWorldPos, worldPos); | float depth = distance(refrWorldPos, worldPos); | ||||
#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. | ||||
float depth = waterDepth / (min(0.5, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0); | float 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 | ||||
// distoFactor controls the amount of distortion relative to wave normals. | // distoFactor controls the amount of distortion relative to wave normals. | ||||
float distoFactor = 0.5 + clamp(depth / 2.0, 0.0, 7.0); | float distoFactor = 0.5 + clamp(depth / 2.0, 0.0, 7.0); | ||||
#if USE_REAL_DEPTH | #if USE_REAL_DEPTH | ||||
// Distort the texture coords under where the water is to simulate refraction. | // Distort the texture coords under where the water is to simulate refraction. | ||||
vec2 shiftedCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5; | vec2 shiftedCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5; | ||||
vec3 refrWorldPos2 = getWorldPositionFromRefractionDepth(shiftedCoords); | vec3 refrWorldPos2 = getWorldPositionFromRefractionDepth(shiftedCoords); | ||||
float newDepth = distance(refrWorldPos2, worldPos); | float newDepth = distance(refrWorldPos2, worldPos); | ||||
// try to correct for fish. In general they'd look weirder without this fix. | // try to correct for fish. In general they'd look weirder without this fix. | ||||
if (depth > newDepth + 3.0) | if (depth > newDepth + 3.0) | ||||
distoFactor /= 2.0; // this in general will not fall on the fish but still look distorted. | distoFactor /= 2.0; // this in general will not fall on the fish but still look distorted. | ||||
else | else | ||||
depth = newDepth; | depth = newDepth; | ||||
#endif | #endif | ||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
depth = max(depth, depthLimit); | depth = max(depth, depthLimit); | ||||
if (waterDepth < 0.0) | if (waterDepth < 0.0) | ||||
depth = 0.0; | depth = 0.0; | ||||
#endif | #endif | ||||
// Distort the texture coords under where the water is to simulate refraction. | // Distort the texture coords under where the water is to simulate refraction. | ||||
vec2 refrCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5; | vec2 refrCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5; | ||||
vec3 refColor = texture2D(refractionMap, refrCoords).rgb; | vec3 refColor = texture2D(refractionMap, refrCoords).rgb; | ||||
// Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red. | // Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red. | ||||
// If we get a pure red fragment, use an undistorted/less distorted coord instead. | // If we get a pure red fragment, use an undistorted/less distorted coord instead. | ||||
// blur the refraction map, distoring using normal so that it looks more random than it really is | // blur the refraction map, distoring using normal so that it looks more random than it really is | ||||
// and thus looks much better. | // and thus looks much better. | ||||
float blur = (0.1 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z; | float blur = (0.1 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z; | ||||
vec4 blurColor = vec4(refColor, 1.0); | vec4 blurColor = vec4(refColor, 1.0); | ||||
vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.x, blur + normal.z)); | vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.x, blur + normal.z)); | ||||
blurColor += vec4(tex.rgb * tex.a, tex.a); | blurColor += vec4(tex.rgb * tex.a, tex.a); | ||||
tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + normal.z)); | tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + normal.z)); | ||||
blurColor += vec4(tex.rgb * tex.a, tex.a); | blurColor += vec4(tex.rgb * tex.a, tex.a); | ||||
tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + normal.x)); | tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + normal.x)); | ||||
blurColor += vec4(tex.rgb * tex.a, tex.a); | blurColor += vec4(tex.rgb * tex.a, tex.a); | ||||
tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.z, -blur)); | tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.z, -blur)); | ||||
blurColor += vec4(tex.rgb * tex.a, tex.a); | blurColor += vec4(tex.rgb * tex.a, tex.a); | ||||
blurColor /= blurColor.a; | blurColor /= blurColor.a; | ||||
float blurFactor = (distoFactor / 7.0); | float blurFactor = (distoFactor / 7.0); | ||||
refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor); | refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor); | ||||
#else // !USE_REFRACTION | #else // !USE_REFRACTION | ||||
#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(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 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, ColextFact); | ||||
float alpha = clamp(depth, 0.0, 1.0); | float alpha = clamp(depth, 0.0, tide) / tide; | ||||
#if !USE_REFRACTION | #if !USE_REFRACTION | ||||
alpha = (1.4 - extFact) * alpha; | alpha = (1.4 - ColextFact) * alpha; | ||||
#endif | #endif | ||||
return vec4(refrColor, alpha); | return vec4(refrColor, alpha); | ||||
} | } | ||||
vec4 getFoam(vec4 fancyeffects, float shadow) | vec4 getFoam(vec4 fancyeffects, float shadow) | ||||
{ | { | ||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
float wavyEffect = waveParams1.r; | float wavyEffect = waveParams1.r; | ||||
float baseScale = waveParams1.g; | float baseScale = waveParams1.g; | ||||
float BigMovement = waveParams2.b; | 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.xy + 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.xy + 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.xy / 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.xy / 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); | ||||
float alpha = (fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5)) * 2.0; | float alpha = (fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5)) * 2.0; | ||||
return vec4(sunColor * shadow + ambient, clamp(alpha, 0.0, 1.0)); | return vec4(sunColor * shadow + ambient, clamp(alpha, 0.0, 1.0)); | ||||
#else | #else | ||||
return vec4(0.0); | return vec4(0.0); | ||||
#endif | #endif | ||||
} | } | ||||
void RealFresnel( float NdotL, vec3 IOR_RGB, out vec3 Frefl, inout vec3 sin_t, inout vec3 cos_t ) | |||||
{ | |||||
vec3 Z2 = WHITE / IOR_RGB; // Assumes n1 = 1 thus Z1 = 1. | |||||
vec3 cos_i = vec3( NdotL ); | |||||
vec3 sin_i = sqrt( WHITE - cos_i*cos_i ); | |||||
sin_t = min(WHITE, sin_i * Z2); // Outputs sin(refraction angle). | |||||
cos_t = sqrt( WHITE - sin_t*sin_t ); // Outputs cos(refraction angle). | |||||
vec3 Rs = (Z2*cos_i-cos_t) / (Z2*cos_i+cos_t); | |||||
vec3 Rp = (Z2*cos_t-cos_i) / (Z2*cos_t+cos_i); | |||||
Frefl = mix( Rs*Rs, Rp*Rp, 0.5 ); // Outputs reflectivity. | |||||
} | |||||
void main() | void main() | ||||
{ | { | ||||
float temp; | |||||
vec2 temp2; | |||||
vec3 temp3; | |||||
vec4 temp4; | |||||
Not Done Inline ActionsVariables should be declared in a place where they're used. Also their names should correspond somehow with their usages. vladislavbelov: Variables should be declared in a place where they're used. Also their names should correspond… | |||||
#if USE_FANCY_EFFECTS | #if USE_FANCY_EFFECTS | ||||
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize); | vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize); | ||||
#else | #else | ||||
vec4 fancyeffects = vec4(0.0); | vec4 fancyeffects = vec4(0.0); | ||||
#endif | #endif | ||||
vec3 eyeVec = normalize(v_eyeVec); | vec3 eyeVec = normalize(v_eyeVec); | ||||
vec3 normal = getNormal(fancyeffects); | vec3 normal = getNormal(fancyeffects); | ||||
vec4 refrColor = getRefraction(normal, eyeVec, fancyeffects.a); | |||||
vec4 reflColor = getReflection(normal, eyeVec); | |||||
// 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, eyeVec), 0.0, 1.0); | float ndotv = clamp(dot(normal, eyeVec), 0.0, 1.0); | ||||
vec3 F_refl_RGB; | |||||
temp4 = getRefractedColor(normal, eyeVec, fancyeffects.a); | |||||
vec3 refrColor = temp4.rgb; | |||||
float tidal = temp4.a; | |||||
// 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 | vec3 n = mix( WHITE, sea_water_refractive_indices_at_15c, tidal ); | ||||
RealFresnel( ndotv, n, F_refl_RGB, temp3, temp3 ); | |||||
vec3 specular = getSpecular(normal, eyeVec); | refrColor = mix( refrColor, refrColor * wetness_RGB, tidal*tidal ); | ||||
vec3 specLight = getReflections(normal, eyeVec).rgb; | |||||
specLight += getSpecularSunlight(normal, eyeVec); | |||||
#if USE_SHADOW | #if USE_SHADOW | ||||
float shadow = getShadowOnLandscape(); | float shadow = getShadowOnLandscape(); | ||||
fresnel = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2); | |||||
#else | #else | ||||
float shadow = 1.0; | float shadow = 1.0; | ||||
#endif | #endif | ||||
vec3 color = mix(refrColor.rgb, reflColor.rgb, fresnel * reflColor.a); | vec3 refrLight = textureCube(skyCube, (vec4(0.0, 1.0, 0.0 , 0.0) * skyBoxRot).xyz, 6.6).rgb; | ||||
color += shadow * specular; | refrLight = refrLight + (sun_dimming_factor * sunColor * 0.5*(shadow+1.0)); // Non-wavey shadows look bad. | ||||
refrLight = refrLight * refrColor; | |||||
vec4 foam = getFoam(fancyeffects, shadow); | vec3 color = mix(refrLight, specLight, F_refl_RGB ); // Period! | ||||
color = clamp(mix(color, foam.rgb, foam.a), 0.0, 1.0); | vec4 foam = getFoam(fancyeffects, getShadow()); | ||||
color = clamp(mix(color, foam.rgb * vec3(tidal), foam.a), 0.0, 1.0); | |||||
color = applyFog(color); | color = applyFog(color); | ||||
gl_FragColor = vec4(color * getLOS(), tidal); | |||||
gl_FragColor = vec4(color * getLOS(), refrColor.a); | |||||
} | } |
Wildfire Games · Phabricator
Space.