forked from 0ad/0ad
Updates the water settings: features can now be enabled individually for more modularity. Fixes a few bugs. Allows it to be run at an acceptable speed in Atlas.
This was SVN commit r12817.
This commit is contained in:
parent
7848f4edef
commit
ed7c66eb82
@ -41,8 +41,15 @@ bpp = 0
|
||||
|
||||
; System settings:
|
||||
|
||||
fancywater = true
|
||||
superfancywater = false
|
||||
waternormals = true
|
||||
waterbinormals = true
|
||||
waterrealdepth = true
|
||||
waterfoam = false
|
||||
watercoastalwaves = false
|
||||
waterrefraction = true
|
||||
waterreflection = true
|
||||
watershadows = false
|
||||
|
||||
shadows = true
|
||||
shadowpcf = true
|
||||
vsync = false
|
||||
|
@ -23,7 +23,7 @@
|
||||
Game Options
|
||||
</object>
|
||||
|
||||
<object size="50%-190 50%-80 50%+140 50%+120">
|
||||
<object size="50%-190 50%-80 50%+140 50%+95">
|
||||
|
||||
<!-- Settings / shadows -->
|
||||
<object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true">Enable Shadows</object>
|
||||
@ -40,15 +40,15 @@
|
||||
</object>
|
||||
|
||||
<!-- Settings / Water -->
|
||||
<object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Water Reflections</object>
|
||||
<!-- <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Water Reflections</object>
|
||||
<object name="fancyWaterCheckbox" size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.fancyWater) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.fancyWater = this.checked;</action>
|
||||
</object>
|
||||
</object>-->
|
||||
|
||||
<!-- Settings / Music-->
|
||||
<object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true">Enable Music</object>
|
||||
<object size="100%-56 90 100%-30 115" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Music</object>
|
||||
<object size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Press">if (this.checked) startMusic(); else stopMusic();</action>
|
||||
</object>
|
||||
|
||||
|
@ -300,7 +300,7 @@
|
||||
<object name="settingsDialogPanel"
|
||||
style="StoneDialog"
|
||||
type="image"
|
||||
size="50%-180 50%-200 50%+180 50%+125"
|
||||
size="50%-180 50%-225 50%+180 50%+250"
|
||||
hidden="true"
|
||||
>
|
||||
<object type="text" style="TitleText" size="50%-96 -16 50%+96 16">Settings</object>
|
||||
@ -323,43 +323,85 @@
|
||||
<action on="Press">renderer.shadowPCF = this.checked;</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Water -->
|
||||
<object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Water Reflections</object>
|
||||
<object name="fancyWaterCheckbox" size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.fancyWater) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.fancyWater = this.checked; </action>
|
||||
<!-- Settings / Water Normals -->
|
||||
<object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Water - 3D Waviness</object>
|
||||
<object name="waterNormalCheckox" size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waternormal) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waternormal = this.checked;</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Advanced Water -->
|
||||
<object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true">Enable Advanced Water</object>
|
||||
<object name="superFancyWaterCheckbox" size="100%-56 90 100%-30 115" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.superFancyWater) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.superFancyWater = this.checked; </action>
|
||||
<!-- Settings / Water Binormals -->
|
||||
<object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true">Water - HQ Waviness</object>
|
||||
<object name="waterBinormalCheckox" size="100%-56 90 100%-30 115" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waterbinormal) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waterbinormal = this.checked;</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Real Depth -->
|
||||
<object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true">Water - Use Actual Depth</object>
|
||||
<object name="waterRealDepthCheckbox" size="100%-56 115 100%-30 140" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waterrealdepth) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waterrealdepth = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Reflection -->
|
||||
<object size="0 135 100%-80 160" type="text" style="RightLabelText" ghost="true">Water - Enable Reflections</object>
|
||||
<object name="waterReflectionCheckbox" size="100%-56 140 100%-30 165" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waterreflection) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waterreflection = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Refraction -->
|
||||
<object size="0 160 100%-80 185" type="text" style="RightLabelText" ghost="true">Water - Enable Refraction</object>
|
||||
<object name="waterRefractionCheckbox" size="100%-56 165 100%-30 190" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waterrefraction) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waterrefraction = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Foam -->
|
||||
<object size="0 185 100%-80 210" type="text" style="RightLabelText" ghost="true">Water - Enable Shore Foam</object>
|
||||
<object name="waterFoamCheckbox" size="100%-56 190 100%-30 215" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.waterfoam) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.waterfoam = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Waves -->
|
||||
<object size="0 210 100%-80 235" type="text" style="RightLabelText" ghost="true">Water - Enable Shore Waves</object>
|
||||
<object name="waterCoastalWavesCheckbox" size="100%-56 215 100%-30 240" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.watercoastalwaves) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.watercoastalwaves = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Shadows -->
|
||||
<object size="0 235 100%-80 260" type="text" style="RightLabelText" ghost="true">Water - Use Surface Shadows</object>
|
||||
<object name="waterShadowsCheckbox" size="100%-56 240 100%-30 265" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.watershadow) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.watershadow = this.checked; </action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Particles -->
|
||||
<object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true">Enable Particles</object>
|
||||
<object name="particlesCheckbox" size="100%-56 115 100%-30 140" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<object size="0 260 100%-80 285" type="text" style="RightLabelText" ghost="true">Enable Particles</object>
|
||||
<object name="particlesCheckbox" size="100%-56 265 100%-30 290" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.particles) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.particles = this.checked;</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Unit Silhouettes -->
|
||||
<object size="0 135 100%-80 160" type="text" style="RightLabelText" ghost="true">Enable Unit Silhouettes</object>
|
||||
<object name="silhouettesCheckbox" size="100%-56 140 100%-30 165" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<object size="0 285 100%-80 310" type="text" style="RightLabelText" ghost="true">Enable Unit Silhouettes</object>
|
||||
<object name="silhouettesCheckbox" size="100%-56 290 100%-30 315" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Load">if (renderer.silhouettes) this.checked = true; else this.checked = false;</action>
|
||||
<action on="Press">renderer.silhouettes = this.checked;</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Music-->
|
||||
<object size="0 160 100%-80 185" type="text" style="RightLabelText" ghost="true">Enable Music</object>
|
||||
<object size="100%-56 165 100%-30 190" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<object size="0 310 100%-80 335" type="text" style="RightLabelText" ghost="true">Enable Music</object>
|
||||
<object size="100%-56 315 100%-30 340" type="checkbox" style="StoneCrossBox" checked="true">
|
||||
<action on="Press">if (this.checked) global.music.start(); else global.music.stop();</action>
|
||||
</object>
|
||||
|
||||
<!-- Settings / Dev Overlay -->
|
||||
<object size="0 185 100%-80 210" type="text" style="RightLabelText" ghost="true">Developer Overlay</object>
|
||||
<object size="100%-56 190 100%-30 215" type="checkbox" style="StoneCrossBox" checked="false">
|
||||
<object size="0 335 100%-80 360" type="text" style="RightLabelText" ghost="true">Developer Overlay</object>
|
||||
<object size="100%-56 340 100%-30 365" type="checkbox" style="StoneCrossBox" checked="false">
|
||||
<action on="Press">toggleDeveloperOverlay();</action>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -4,9 +4,6 @@ uniform vec3 ambient;
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunColor;
|
||||
uniform vec3 cameraPos;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D reflectionMap;
|
||||
uniform sampler2D refractionMap;
|
||||
uniform sampler2D losMap;
|
||||
uniform float shininess; // Blinn-Phong specular strength
|
||||
uniform float specularStrength; // Scaling for specular reflection (specular color is (this,this,this))
|
||||
@ -23,15 +20,30 @@ uniform vec2 fogParams;
|
||||
uniform vec2 screenSize;
|
||||
uniform float time;
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
varying vec3 worldPos;
|
||||
varying float waterDepth;
|
||||
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
#if USE_BINORMALS
|
||||
uniform sampler2D normalMap2;
|
||||
#endif
|
||||
#if USE_REFLECTION
|
||||
uniform sampler2D reflectionMap;
|
||||
#endif
|
||||
#if USE_REFRACTION
|
||||
uniform sampler2D refractionMap;
|
||||
#endif
|
||||
#if USE_REAL_DEPTH
|
||||
uniform sampler2D depthTex;
|
||||
#endif
|
||||
#if USE_FOAM || USE_WAVES
|
||||
uniform sampler2D heightmap;
|
||||
uniform sampler2D infoTex;
|
||||
uniform sampler2D normalMap2;
|
||||
uniform sampler2D Foam;
|
||||
uniform sampler2D depthTex;
|
||||
uniform sampler2D waveTex;
|
||||
|
||||
#if USE_SHADOW
|
||||
#endif
|
||||
#if USE_SHADOWS
|
||||
varying vec4 v_shadow;
|
||||
#if USE_SHADOW_SAMPLER
|
||||
uniform sampler2DShadow shadowTex;
|
||||
@ -41,17 +53,9 @@ uniform float time;
|
||||
#else
|
||||
uniform sampler2D shadowTex;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
varying vec3 worldPos;
|
||||
varying float waterDepth;
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
float get_shadow(vec4 coords)
|
||||
{
|
||||
#if USE_SHADOW && !DISABLE_RECEIVE_SHADOWS
|
||||
float get_shadow(vec4 coords)
|
||||
{
|
||||
#if USE_SHADOWS && !DISABLE_RECEIVE_SHADOWS
|
||||
#if USE_SHADOW_SAMPLER
|
||||
#if USE_SHADOW_PCF
|
||||
vec2 offset = fract(coords.xy - 0.5);
|
||||
@ -73,7 +77,7 @@ float get_shadow(vec4 coords)
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 get_fog(vec3 color)
|
||||
@ -94,7 +98,7 @@ vec3 get_fog(vec3 color)
|
||||
|
||||
void main()
|
||||
{
|
||||
#if USE_SUPERFANCYWATER
|
||||
#if USE_FOAM || USE_WAVES
|
||||
vec4 heightmapval = texture2D(heightmap, gl_TexCoord[3].zw);
|
||||
vec2 beachOrientation = heightmapval.rb - vec2(0.5,0.5);
|
||||
float distToShore = heightmapval.a;
|
||||
@ -108,32 +112,39 @@ void main()
|
||||
vec3 reflColor, refrColor, specular;
|
||||
float losMod;
|
||||
|
||||
float wavyFactor = waviness * 0.125;
|
||||
|
||||
// always done cause this is also used, even when not using normals, by the refraction.
|
||||
vec3 ww = texture2D(normalMap, (gl_TexCoord[0].st) * mix(2.0,0.8,waviness/10.0) +gl_TexCoord[0].zw).xzy;
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
#if USE_NORMALS
|
||||
#if USE_BINORMALS
|
||||
vec3 ww2 = texture2D(normalMap2, (gl_TexCoord[0].st) * mix(2.0,0.8,waviness/10.0) +gl_TexCoord[0].zw).xzy;
|
||||
ww = mix(ww, ww2, mod(time * 60.0, 8.0) / 8.0);
|
||||
#endif
|
||||
|
||||
#if USE_WAVES
|
||||
vec3 waves = texture2D(waveTex, gl_FragCoord.xy/screenSize).rbg - vec3(0.5,0.5,0.5);
|
||||
float waveFoam = 0.0;//texture2D(waveTex, gl_FragCoord.xy/screenSize).a;
|
||||
n = normalize(mix(waves, ww - vec3(0.5, 0.5, 0.5) , clamp(distToShore*3.0,0.4,1.0)));
|
||||
#else
|
||||
n = normalize(ww - vec3(0.5, 0.5, 0.5));
|
||||
#endif
|
||||
|
||||
float wavyFactor = waviness * 0.125;
|
||||
|
||||
n = mix(vec3(0.0,1.0,0.0),n,wavyFactor);
|
||||
#else
|
||||
n = vec3(0.0,1.0,0.0);
|
||||
#endif
|
||||
|
||||
l = -sunDir;
|
||||
v = normalize(cameraPos - worldPos);
|
||||
h = normalize(l + v);
|
||||
|
||||
ndotl = (dot(n, l) + 1.0) /2.0;
|
||||
ndotl = (dot(n, l) + 1.0)/2.0;
|
||||
ndoth = dot(n, h);
|
||||
ndotv = dot(n, v);
|
||||
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
#if USE_REAL_DEPTH
|
||||
// Don't change these two. They should match the values in the config (TODO: dec uniforms).
|
||||
float zNear = 2.0;
|
||||
float zFar = 4096.0;
|
||||
@ -165,9 +176,9 @@ void main()
|
||||
float distoFactor = clamp(waterDepth2/10.0,0.0,7.0);
|
||||
#endif
|
||||
|
||||
fresnel = pow(1.0 - ndotv, 1.3333);// approximation
|
||||
fresnel = pow(1.0 - ndotv, 1.3333); // approximation
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
#if USE_FOAM
|
||||
// texture is rotated 90°, moves slowly.
|
||||
vec2 foam1RC = vec2(-gl_TexCoord[0].t,gl_TexCoord[0].s)*1.3 - 0.012*n.xz + vec2(time*0.004,time*0.003);
|
||||
// texture is not rotated, moves twice faster in the opposite direction, translated.
|
||||
@ -181,27 +192,22 @@ void main()
|
||||
|
||||
if ((1.0 - finalFoam.r) >= wavyFactor)
|
||||
finalFoam = vec3(0.0);
|
||||
|
||||
#if USE_WAVES && USE_NORMALS
|
||||
// waves bypass the regular foam restrictions.
|
||||
finalFoam += min( max(0.0,-waves.b) * texture2D(Foam, foam1RC).r, 1.0)*3.0 * max(0.0,wavyFactor-0.1);
|
||||
#endif
|
||||
finalFoam *= sunColor;
|
||||
#endif
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
#if USE_REFRACTION
|
||||
#if USE_REAL_DEPTH
|
||||
refrCoords = clamp( (0.5*gl_TexCoord[2].xy - n.xz * distoFactor) / gl_TexCoord[2].w + 0.5,0.0,1.0); // Unbias texture coords
|
||||
#else
|
||||
refrCoords = clamp( (0.5*gl_TexCoord[2].xy - n.xz * 6.0) / gl_TexCoord[2].w + 0.5,0.0,1.0); // Unbias texture coords
|
||||
#endif
|
||||
|
||||
reflCoords = clamp( (0.5*gl_TexCoord[1].xy + 10.0*n.xz) / gl_TexCoord[1].w + 0.5,0.0,1.0); // Unbias texture coords
|
||||
reflColor = mix(texture2D(reflectionMap, reflCoords).rgb, sunColor * reflectionTint, reflectionTintStrength);
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
|
||||
float luminance = (1.0 - clamp((waterDepth2/mix(300.0,1.0, pow(murkiness,0.2) )), 0.0, 1.0));
|
||||
float colorExtinction = clamp(waterDepth2*murkiness/5.0,0.0,1.0);
|
||||
refrColor = (0.5 + 0.5*ndotl) * mix(color,mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
|
||||
#else
|
||||
refrCoords = clamp( (0.5*gl_TexCoord[2].xy - n.xz * 6.0) / gl_TexCoord[2].w + 0.5,0.0,1.0); // Unbias texture coords
|
||||
// fake it. It won't look as good but it will give a similar result.
|
||||
float perceivedDepth = waterDepth / v.y;
|
||||
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
|
||||
@ -209,29 +215,82 @@ void main()
|
||||
float colorExtinction = clamp(perceivedDepth*murkiness/5.0,0.0,1.0);
|
||||
refrColor = (0.5 + 0.5*ndotl) * mix(color,mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
|
||||
#endif
|
||||
#else
|
||||
float alphaCoeff = 0.0;
|
||||
#if USE_REAL_DEPTH
|
||||
alphaCoeff = clamp(waterDepth2*murkiness/5.0,0.0,1.0);
|
||||
#else
|
||||
alphaCoeff = clamp((waterDepth / v.y)*murkiness/5.0,0.0,1.0);
|
||||
#endif
|
||||
refrColor = color;
|
||||
#endif
|
||||
|
||||
#if !USE_NORMALS
|
||||
// we're not using normals. Simulate by applying a B&W effect.
|
||||
refrColor *= (ww*2.0).x;
|
||||
#endif
|
||||
|
||||
#if USE_REFLECTION
|
||||
reflCoords = clamp( (0.5*gl_TexCoord[1].xy + 10.0*n.xz) / gl_TexCoord[1].w + 0.5,0.0,1.0); // Unbias texture coords
|
||||
reflColor = mix(texture2D(reflectionMap, reflCoords).rgb, sunColor * reflectionTint, reflectionTintStrength);
|
||||
#else
|
||||
// TODO: implement some sort of skybox rendering.
|
||||
reflColor = mix( (sunColor + vec3(0.565,0.843,0.961))/1.85, reflectionTint, reflectionTintStrength);
|
||||
#endif
|
||||
|
||||
specular = pow(ndoth, shininess) * sunColor * specularStrength;
|
||||
|
||||
losMod = texture2D(losMap, gl_TexCoord[3].st).a;
|
||||
losMod = losMod < 0.03 ? 0.0 : losMod;
|
||||
|
||||
#if USE_SUPERFANCYWATER && USE_SHADOW
|
||||
vec3 colour;
|
||||
#if USE_SHADOWS
|
||||
float shadow = get_shadow(vec4(v_shadow.xy - 8.0*waviness*n.xz, v_shadow.zw));
|
||||
float fresShadow = mix(fresnel, fresnel*shadow, 0.05 + (murkiness * 0.15));
|
||||
vec3 colour = mix(refrColor*(shadow/5.0 + 0.8) + fresnel*shadow*specular, reflColor + fresnel*shadow*specular, fresShadow) + max(ndotl,0.4)*(finalFoam)*(shadow/2.0 + 0.5);
|
||||
colour = mix( texture2D(refractionMap, (0.5*gl_TexCoord[2].xy) / gl_TexCoord[2].w + 0.5).rgb ,colour, clamp(waterDepth2,0.0,1.0));
|
||||
#if USE_FOAM
|
||||
colour = mix(refrColor*(shadow/5.0 + 0.8) + fresnel*shadow*specular, reflColor + fresnel*shadow*specular, fresShadow) + max(ndotl,0.4)*(finalFoam)*(shadow/2.0 + 0.5);
|
||||
#else
|
||||
vec3 colour = mix(refrColor + fresnel*specular, reflColor + fresnel*specular, fresnel);
|
||||
colour = mix(refrColor*(shadow/5.0 + 0.8) + fresnel*shadow*specular, reflColor + fresnel*shadow*specular, fresShadow);
|
||||
#endif
|
||||
#else
|
||||
#if USE_FOAM
|
||||
colour = mix(refrColor + fresnel*specular, reflColor + fresnel*specular, fresnel) + max(ndotl,0.4)*(finalFoam);
|
||||
#else
|
||||
colour = mix(refrColor + fresnel*specular, reflColor + fresnel*specular, fresnel);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USE_REFRACTION
|
||||
#if USE_REAL_DEPTH
|
||||
colour = mix(texture2D(refractionMap, (0.5*gl_TexCoord[2].xy) / gl_TexCoord[2].w + 0.5).rgb ,colour, clamp(waterDepth2,0.0,1.0));
|
||||
#else
|
||||
colour = mix(texture2D(refractionMap, (0.5*gl_TexCoord[2].xy) / gl_TexCoord[2].w + 0.5).rgb ,colour, clamp(perceivedDepth,0.0,1.0));
|
||||
#endif
|
||||
#else
|
||||
// I'm not even sure what this does.
|
||||
//colour = mix( texture2D(refractionMap, (0.5*gl_TexCoord[2].xy) / gl_TexCoord[2].w + 0.5).rgb ,colour, clamp(perceivedDepth,0.0,1.0));
|
||||
#endif
|
||||
|
||||
gl_FragColor.rgb = get_fog(colour) * losMod;
|
||||
|
||||
#if USE_SUPERFANCYWATER
|
||||
gl_FragColor.a = clamp(distToShore-0.012,waterDepth2/2.0,1.0) + finalFoam.r * losMod;
|
||||
#if USE_REAL_DEPTH
|
||||
float alpha = clamp(waterDepth2*(5.0*murkiness),0.0,1.0);
|
||||
#if !USE_REFRACTION
|
||||
alpha *= alphaCoeff;
|
||||
#endif
|
||||
#if USE_FOAM
|
||||
alpha += finalFoam.r * losMod;
|
||||
#endif
|
||||
gl_FragColor.a = alpha;
|
||||
#else
|
||||
// Make alpha vary based on both depth (so it blends with the shore) and view angle (make it
|
||||
// become opaque faster at lower view angles so we can't look "underneath" the water plane)
|
||||
t = 18.0 * max(0.0, 0.9 - v.y);
|
||||
gl_FragColor.a = clamp(0.15 * waterDepth * (1.2 + t + fresnel),0.0,1.0);
|
||||
t = 30.0 * max(0.0, 0.9 - v.y);
|
||||
float alpha = clamp(0.15 * waterDepth * (1.2 + t + fresnel),0.0,1.0);
|
||||
#if !USE_REFRACTION
|
||||
gl_FragColor.a = alpha * alphaCoeff;
|
||||
#else
|
||||
gl_FragColor.a = alpha;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -17,8 +17,9 @@ uniform float mapSize;
|
||||
|
||||
varying vec3 worldPos;
|
||||
varying float waterDepth;
|
||||
varying vec4 v_shadow;
|
||||
|
||||
#if USE_SHADOW
|
||||
varying vec4 v_shadow;
|
||||
#endif
|
||||
attribute vec3 a_vertex;
|
||||
attribute vec4 a_encodedDepth;
|
||||
|
||||
@ -34,7 +35,7 @@ void main()
|
||||
|
||||
gl_TexCoord[3].zw = vec2(a_vertex.xz)/mapSize;
|
||||
|
||||
#if USE_SHADOW && USE_SUPERFANCYWATER
|
||||
#if USE_SHADOW && USE_SHADOWS
|
||||
v_shadow = shadowTransform * vec4(a_vertex, 1.0);
|
||||
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
|
||||
v_shadow.xy *= shadowScale.xy;
|
||||
|
@ -38,8 +38,16 @@ CStr g_PlayerName = "";
|
||||
|
||||
bool g_Shadows = false;
|
||||
bool g_ShadowPCF = false;
|
||||
bool g_FancyWater = false;
|
||||
bool g_SuperFancyWater = false;
|
||||
|
||||
bool g_WaterNormal = false;
|
||||
bool g_WaterBinormal = false;
|
||||
bool g_WaterRealDepth = false;
|
||||
bool g_WaterFoam = false;
|
||||
bool g_WaterCoastalWaves = false;
|
||||
bool g_WaterRefraction = false;
|
||||
bool g_WaterReflection = false;
|
||||
bool g_WaterShadows = false;
|
||||
|
||||
bool g_Particles = false;
|
||||
bool g_Silhouettes = false;
|
||||
bool g_ShowSky = false;
|
||||
@ -81,11 +89,20 @@ static void LoadGlobals()
|
||||
CFG_GET_USER_VAL("playername", String, g_PlayerName);
|
||||
CFG_GET_USER_VAL("shadows", Bool, g_Shadows);
|
||||
CFG_GET_USER_VAL("shadowpcf", Bool, g_ShadowPCF);
|
||||
CFG_GET_USER_VAL("fancywater", Bool, g_FancyWater);
|
||||
CFG_GET_USER_VAL("superfancywater", Bool, g_SuperFancyWater);
|
||||
if (g_SuperFancyWater && !g_FancyWater) {
|
||||
g_SuperFancyWater = false;
|
||||
}
|
||||
|
||||
CFG_GET_USER_VAL("waternormals",Bool, g_WaterNormal);
|
||||
CFG_GET_USER_VAL("waterbinormals",Bool, g_WaterBinormal);
|
||||
if (g_WaterBinormal && !g_WaterNormal)
|
||||
g_WaterBinormal = false;
|
||||
CFG_GET_USER_VAL("waterrealdepth",Bool, g_WaterRealDepth);
|
||||
CFG_GET_USER_VAL("waterfoam",Bool, g_WaterFoam);
|
||||
CFG_GET_USER_VAL("watercoastalwaves",Bool, g_WaterCoastalWaves);
|
||||
if (g_WaterCoastalWaves && !g_WaterNormal)
|
||||
g_WaterCoastalWaves = false;
|
||||
CFG_GET_USER_VAL("waterrefraction",Bool, g_WaterRefraction);
|
||||
CFG_GET_USER_VAL("waterreflection",Bool, g_WaterReflection);
|
||||
CFG_GET_USER_VAL("watershadows",Bool, g_WaterShadows);
|
||||
|
||||
CFG_GET_USER_VAL("renderpath", String, g_RenderPath);
|
||||
CFG_GET_USER_VAL("particles", Bool, g_Particles);
|
||||
CFG_GET_USER_VAL("silhouettes", Bool, g_Silhouettes);
|
||||
|
@ -49,10 +49,24 @@ extern CStr g_PlayerName;
|
||||
|
||||
// flag to switch on shadows
|
||||
extern bool g_Shadows;
|
||||
// flag to switch on reflective/refractive water
|
||||
extern bool g_FancyWater;
|
||||
// flag to switch on foam, normal interpolation, shadows on water
|
||||
extern bool g_SuperFancyWater;
|
||||
|
||||
// Use real normals for ocean-wave rendering, instead of applying them as a flat texture.
|
||||
extern bool g_WaterNormal;
|
||||
// Use interpolated normals, smoother. Requires g_WaterNormal.
|
||||
extern bool g_WaterBinormal;
|
||||
// Use real depth for water rendering.
|
||||
extern bool g_WaterRealDepth;
|
||||
// Show foam near the shores depending on waviness.
|
||||
extern bool g_WaterFoam;
|
||||
// Show coastal breaking waves.
|
||||
extern bool g_WaterCoastalWaves;
|
||||
// Use a real refraction map and not transparency.
|
||||
extern bool g_WaterRefraction;
|
||||
// Use a real reflection map and not a skybox texture.
|
||||
extern bool g_WaterReflection;
|
||||
// Enable on-water shadows.
|
||||
extern bool g_WaterShadows;
|
||||
|
||||
// flag to switch on shadow PCF
|
||||
extern bool g_ShadowPCF;
|
||||
// flag to switch on particles rendering
|
||||
|
@ -574,8 +574,16 @@ static void InitRenderer()
|
||||
// set renderer options from command line options - NOVBO must be set before opening the renderer
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_NOVBO, g_NoGLVBO);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, g_Shadows);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_FANCYWATER, g_FancyWater);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_SUPERFANCYWATER, (g_SuperFancyWater && g_FancyWater) );
|
||||
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERNORMAL, g_WaterNormal);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERBINORMAL, g_WaterBinormal);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERREALDEPTH, g_WaterRealDepth);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERFOAM, g_WaterFoam);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERCOASTALWAVES, g_WaterCoastalWaves);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERREFLECTION, g_WaterRefraction);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERREFRACTION, g_WaterReflection);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERSHADOW, g_WaterShadows);
|
||||
|
||||
g_Renderer.SetRenderPath(CRenderer::GetRenderPathByName(g_RenderPath));
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWPCF, g_ShadowPCF);
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_PARTICLES, g_Particles);
|
||||
|
@ -123,15 +123,30 @@ void SetDisableShadowPCF(void* UNUSED(cbdata), bool disabled)
|
||||
|
||||
void SetDisableFancyWater(void* UNUSED(cbdata), bool disabled)
|
||||
{
|
||||
if (!IsOverridden("fancywater")) {
|
||||
g_FancyWater = !disabled;
|
||||
g_SuperFancyWater = !disabled;
|
||||
if (!IsOverridden("waternormals"))
|
||||
{
|
||||
g_WaterNormal = !disabled;
|
||||
if (!g_WaterNormal)
|
||||
g_WaterBinormal = false;
|
||||
}
|
||||
if (!IsOverridden("waterbinormals"))
|
||||
g_WaterBinormal = !disabled;
|
||||
if (!IsOverridden("waterrealdepth"))
|
||||
g_WaterRealDepth = !disabled;
|
||||
if (!IsOverridden("waterfoam"))
|
||||
g_WaterFoam = !disabled;
|
||||
if (!IsOverridden("watercoastalwaves"))
|
||||
g_WaterCoastalWaves = !disabled;
|
||||
if (!IsOverridden("waterrefraction"))
|
||||
g_WaterRefraction = !disabled;
|
||||
if (!IsOverridden("waterreflection"))
|
||||
g_WaterReflection = !disabled;
|
||||
if (!IsOverridden("watershadows"))
|
||||
g_WaterShadows = !disabled;
|
||||
}
|
||||
|
||||
void SetRenderPath(void* UNUSED(cbdata), std::string renderpath)
|
||||
{
|
||||
if (!IsOverridden("fancywater"))
|
||||
g_RenderPath = renderpath;
|
||||
}
|
||||
|
||||
|
@ -429,8 +429,6 @@ CRenderer::CRenderer()
|
||||
|
||||
m_Options.m_NoVBO = false;
|
||||
m_Options.m_RenderPath = RP_DEFAULT;
|
||||
m_Options.m_FancyWater = false;
|
||||
m_Options.m_SuperFancyWater = false;
|
||||
m_Options.m_Shadows = false;
|
||||
m_Options.m_ShadowAlphaFix = true;
|
||||
m_Options.m_ARBProgramShadow = true;
|
||||
@ -469,8 +467,16 @@ CRenderer::CRenderer()
|
||||
|
||||
m_Stats.Reset();
|
||||
AddLocalProperty(L"particles", &m_Options.m_Particles, false);
|
||||
AddLocalProperty(L"fancyWater", &m_Options.m_FancyWater, false);
|
||||
AddLocalProperty(L"superFancyWater", &m_Options.m_SuperFancyWater, false);
|
||||
|
||||
AddLocalProperty(L"waternormal", &m_Options.m_WaterNormal, false);
|
||||
AddLocalProperty(L"waterbinormal", &m_Options.m_WaterBinormal, false);
|
||||
AddLocalProperty(L"waterrealdepth", &m_Options.m_WaterRealDepth, false);
|
||||
AddLocalProperty(L"waterreflection", &m_Options.m_WaterReflection, false);
|
||||
AddLocalProperty(L"waterrefraction", &m_Options.m_WaterRefraction, false);
|
||||
AddLocalProperty(L"waterfoam", &m_Options.m_WaterFoam, false);
|
||||
AddLocalProperty(L"watercoastalwaves", &m_Options.m_WaterCoastalWaves, false);
|
||||
AddLocalProperty(L"watershadow", &m_Options.m_WaterShadow, false);
|
||||
|
||||
AddLocalProperty(L"horizonHeight", &m->skyManager.m_HorizonHeight, false);
|
||||
AddLocalProperty(L"waterMurkiness", &m->waterManager.m_Murkiness, false);
|
||||
AddLocalProperty(L"waterReflTintStrength", &m->waterManager.m_ReflectionTintStrength, false);
|
||||
@ -682,11 +688,29 @@ void CRenderer::SetOptionBool(enum Option opt,bool value)
|
||||
m_Options.m_Shadows = value;
|
||||
MakeShadersDirty();
|
||||
break;
|
||||
case OPT_FANCYWATER:
|
||||
m_Options.m_FancyWater = value;
|
||||
case OPT_WATERNORMAL:
|
||||
m_Options.m_WaterNormal = value;
|
||||
break;
|
||||
case OPT_SUPERFANCYWATER:
|
||||
m_Options.m_SuperFancyWater = value;
|
||||
case OPT_WATERBINORMAL:
|
||||
m_Options.m_WaterBinormal = value;
|
||||
break;
|
||||
case OPT_WATERREALDEPTH:
|
||||
m_Options.m_WaterRealDepth = value;
|
||||
break;
|
||||
case OPT_WATERFOAM:
|
||||
m_Options.m_WaterFoam = value;
|
||||
break;
|
||||
case OPT_WATERCOASTALWAVES:
|
||||
m_Options.m_WaterCoastalWaves = value;
|
||||
break;
|
||||
case OPT_WATERREFLECTION:
|
||||
m_Options.m_WaterReflection = value;
|
||||
break;
|
||||
case OPT_WATERREFRACTION:
|
||||
m_Options.m_WaterRefraction = value;
|
||||
break;
|
||||
case OPT_WATERSHADOW:
|
||||
m_Options.m_WaterShadow = value;
|
||||
break;
|
||||
case OPT_SHADOWPCF:
|
||||
m_Options.m_ShadowPCF = value;
|
||||
@ -716,10 +740,22 @@ bool CRenderer::GetOptionBool(enum Option opt) const
|
||||
return m_Options.m_NoVBO;
|
||||
case OPT_SHADOWS:
|
||||
return m_Options.m_Shadows;
|
||||
case OPT_FANCYWATER:
|
||||
return m_Options.m_FancyWater;
|
||||
case OPT_SUPERFANCYWATER:
|
||||
return m_Options.m_SuperFancyWater;
|
||||
case OPT_WATERNORMAL:
|
||||
return m_Options.m_WaterNormal;
|
||||
case OPT_WATERBINORMAL:
|
||||
return m_Options.m_WaterBinormal;
|
||||
case OPT_WATERREALDEPTH:
|
||||
return m_Options.m_WaterRealDepth;
|
||||
case OPT_WATERFOAM:
|
||||
return m_Options.m_WaterFoam;
|
||||
case OPT_WATERCOASTALWAVES:
|
||||
return m_Options.m_WaterCoastalWaves;
|
||||
case OPT_WATERREFLECTION:
|
||||
return m_Options.m_WaterReflection;
|
||||
case OPT_WATERREFRACTION:
|
||||
return m_Options.m_WaterRefraction;
|
||||
case OPT_WATERSHADOW:
|
||||
return m_Options.m_WaterShadow;
|
||||
case OPT_SHADOWPCF:
|
||||
return m_Options.m_ShadowPCF;
|
||||
case OPT_PARTICLES:
|
||||
@ -815,10 +851,6 @@ void CRenderer::BeginFrame()
|
||||
if (m->ShadersDirty)
|
||||
ReloadShaders();
|
||||
|
||||
// this is ugly, I should do otherwise
|
||||
if (g_GameRestarted)
|
||||
m_WaterManager->m_NeedsReloading = true;
|
||||
|
||||
m->Model.ModShader->SetShadowMap(&m->shadow);
|
||||
m->Model.ModShader->SetLightEnv(m_LightEnv);
|
||||
}
|
||||
@ -1446,8 +1478,12 @@ void CRenderer::RenderSubmissions()
|
||||
waterScissor = m->terrainRenderer.ScissorWater(m_ViewCamera.GetViewProjection());
|
||||
if (waterScissor.GetVolume() > 0 && m_WaterManager->WillRenderFancyWater())
|
||||
{
|
||||
SScreenRect reflectionScissor = RenderReflections(context, waterScissor);
|
||||
SScreenRect refractionScissor = RenderRefractions(context, waterScissor);
|
||||
SScreenRect reflectionScissor;
|
||||
if (m_Options.m_WaterReflection)
|
||||
reflectionScissor = RenderReflections(context, waterScissor);
|
||||
SScreenRect refractionScissor;
|
||||
if (m_Options.m_WaterRefraction)
|
||||
refractionScissor = RenderRefractions(context, waterScissor);
|
||||
|
||||
PROFILE3_GPU("water scissor");
|
||||
SScreenRect dirty;
|
||||
|
@ -80,8 +80,14 @@ public:
|
||||
enum Option {
|
||||
OPT_NOVBO,
|
||||
OPT_SHADOWS,
|
||||
OPT_FANCYWATER,
|
||||
OPT_SUPERFANCYWATER,
|
||||
OPT_WATERNORMAL,
|
||||
OPT_WATERBINORMAL,
|
||||
OPT_WATERREALDEPTH,
|
||||
OPT_WATERFOAM,
|
||||
OPT_WATERCOASTALWAVES,
|
||||
OPT_WATERREFLECTION,
|
||||
OPT_WATERREFRACTION,
|
||||
OPT_WATERSHADOW,
|
||||
OPT_SHADOWPCF,
|
||||
OPT_PARTICLES,
|
||||
OPT_SILHOUETTES,
|
||||
@ -124,8 +130,16 @@ public:
|
||||
struct Options {
|
||||
bool m_NoVBO;
|
||||
bool m_Shadows;
|
||||
bool m_FancyWater;
|
||||
bool m_SuperFancyWater;
|
||||
|
||||
bool m_WaterNormal;
|
||||
bool m_WaterBinormal;
|
||||
bool m_WaterRealDepth;
|
||||
bool m_WaterFoam;
|
||||
bool m_WaterCoastalWaves;
|
||||
bool m_WaterRefraction;
|
||||
bool m_WaterReflection;
|
||||
bool m_WaterShadow;
|
||||
|
||||
RenderPath m_RenderPath;
|
||||
bool m_ShadowAlphaFix;
|
||||
bool m_ARBProgramShadow;
|
||||
|
@ -651,28 +651,36 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
|
||||
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
||||
CShaderDefines defines = context;
|
||||
// deactivate superfancy in Atlas so it won't lag.
|
||||
bool superFancy = WaterMgr->WillRenderSuperFancyWater() && !g_AtlasGameLoop->running;
|
||||
|
||||
// Don't use m_NeedsReloading since that also restarts the map texture generation (slow).
|
||||
bool reload = false;
|
||||
if (superFancy && !WaterMgr->m_RunningSuperFancy)
|
||||
{
|
||||
reload = true;
|
||||
WaterMgr->m_RunningSuperFancy = true;
|
||||
}
|
||||
else if (!superFancy && WaterMgr->m_RunningSuperFancy)
|
||||
{
|
||||
reload = true;
|
||||
WaterMgr->m_RunningSuperFancy = false;
|
||||
}
|
||||
WaterMgr->updateQuality();
|
||||
|
||||
// If we're using fancy water, make sure its shader is loaded
|
||||
if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading || reload)
|
||||
if (!m->fancyWaterShader || (WaterMgr->m_NeedsReloading && (!g_AtlasGameLoop->running || !WaterMgr->m_TerrainChangeThisTurn) ))
|
||||
{
|
||||
if (superFancy)
|
||||
defines.Add("USE_SUPERFANCYWATER", "1");
|
||||
else
|
||||
defines.Add("USE_SUPERFANCYWATER", "0");
|
||||
if(WaterMgr->m_WaterNormal)
|
||||
defines.Add("USE_NORMALS","1");
|
||||
if(WaterMgr->m_WaterBinormal)
|
||||
defines.Add("USE_BINORMALS","1");
|
||||
if(WaterMgr->m_WaterRealDepth)
|
||||
defines.Add("USE_REAL_DEPTH","1");
|
||||
if(WaterMgr->m_WaterFoam)
|
||||
defines.Add("USE_FOAM","1");
|
||||
if(WaterMgr->m_WaterCoastalWaves)
|
||||
defines.Add("USE_WAVES","1");
|
||||
if(WaterMgr->m_WaterRefraction)
|
||||
defines.Add("USE_REFRACTION","1");
|
||||
if(WaterMgr->m_WaterReflection)
|
||||
defines.Add("USE_REFLECTION","1");
|
||||
if(shadow && WaterMgr->m_WaterShadows)
|
||||
defines.Add("USE_SHADOWS","1");
|
||||
|
||||
m->wavesShader = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", defines);
|
||||
if (!m->wavesShader)
|
||||
{
|
||||
LOGERROR(L"Failed to load waves shader. Deactivating waves.\n");
|
||||
g_Renderer.SetOptionBool(CRenderer::OPT_WATERCOASTALWAVES, false);
|
||||
defines.Add("USE_WAVES","0");
|
||||
}
|
||||
|
||||
// haven't updated the ARB shader yet so I'll always load the GLSL
|
||||
/*if (!g_Renderer.m_Options.m_PreferGLSL && !superFancy)
|
||||
@ -680,32 +688,34 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
else*/
|
||||
m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_high", defines);
|
||||
|
||||
m->wavesShader = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", defines);
|
||||
|
||||
if (!m->fancyWaterShader)
|
||||
{
|
||||
LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
|
||||
g_Renderer.m_Options.m_FancyWater = false;
|
||||
g_Renderer.m_Options.m_SuperFancyWater = false;
|
||||
WaterMgr->m_RenderWater = false;
|
||||
return false;
|
||||
}
|
||||
if (WaterMgr->m_NeedsReloading)
|
||||
// we need to actually recompute the whole map settings.
|
||||
if (WaterMgr->m_NeedsFullReloading)
|
||||
{
|
||||
delete[] WaterMgr->m_Heightmap;
|
||||
WaterMgr->m_Heightmap = NULL;
|
||||
glDeleteTextures(1, &WaterMgr->m_HeightmapTexture);
|
||||
WaterMgr->m_NeedsReloading = false;
|
||||
WaterMgr->m_NeedsFullReloading = false;
|
||||
|
||||
WaterMgr->m_waveTT = 0;
|
||||
WaterMgr->m_depthTT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_AtlasGameLoop->running)
|
||||
WaterMgr->m_TerrainChangeThisTurn = false;
|
||||
|
||||
CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
|
||||
|
||||
GLuint depthTex;
|
||||
// TODO: ultimately, this should go in the water manager for readibility.
|
||||
if (superFancy)
|
||||
// creating the real depth texture using the depth buffer.
|
||||
if (WaterMgr->m_WaterRealDepth)
|
||||
{
|
||||
if (WaterMgr->m_depthTT == 0)
|
||||
{
|
||||
@ -725,12 +735,11 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// If we have not already calculated the heightmap, do it once and for all.
|
||||
// TODO: in Atlas this is recomputed every frame, which is way too slow. Temporary fix is disabling it in Atlas.
|
||||
if (WaterMgr->m_Heightmap == NULL)
|
||||
WaterMgr->CreateSuperfancyInfo();
|
||||
}
|
||||
// Calculating the advanced informations about Foam and all if the quality calls for it.
|
||||
if (WaterMgr->m_Heightmap == NULL && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
|
||||
WaterMgr->CreateSuperfancyInfo();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -743,8 +752,8 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
|
||||
GLuint FramebufferName = 0;
|
||||
|
||||
// rendering waves to a framebuffer if super fancy water is activated
|
||||
if (superFancy)
|
||||
// rendering waves to a framebuffer
|
||||
if (WaterMgr->m_WaterCoastalWaves)
|
||||
{
|
||||
// Save the post-processing framebuffer.
|
||||
GLint fbo;
|
||||
@ -803,19 +812,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
|
||||
m->fancyWaterShader->Bind();
|
||||
|
||||
m->fancyWaterShader->BindTexture("normalMap", WaterMgr->m_NormalMap[curTex]);
|
||||
|
||||
if (superFancy)
|
||||
{
|
||||
m->fancyWaterShader->BindTexture("normalMap2", WaterMgr->m_NormalMap[nexTex]);
|
||||
m->fancyWaterShader->BindTexture("Foam", WaterMgr->m_Foam);
|
||||
m->fancyWaterShader->BindTexture("heightmap", WaterMgr->m_HeightmapTexture);
|
||||
m->fancyWaterShader->BindTexture("infoTex", WaterMgr->m_OtherInfoTex);
|
||||
m->fancyWaterShader->BindTexture("depthTex", WaterMgr->m_depthTT);
|
||||
m->fancyWaterShader->BindTexture("waveTex", WaterMgr->m_waveTT);
|
||||
|
||||
m->fancyWaterShader->Uniform("mapSize", (float)(WaterMgr->m_TexSize));
|
||||
}
|
||||
// Shift the texture coordinates by these amounts to make the water "flow"
|
||||
float tx = -fmod(time, 81.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(81.0/ (WaterMgr->m_Waviness/20.0 + 0.8) );
|
||||
float ty = -fmod(time, 34.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(34.0/ (WaterMgr->m_Waviness/20.0 + 0.8) );
|
||||
@ -825,14 +822,31 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
const CCamera& camera = g_Renderer.GetViewCamera();
|
||||
CVector3D camPos = camera.m_Orientation.GetTranslation();
|
||||
|
||||
// Bind reflection and refraction textures
|
||||
m->fancyWaterShader->BindTexture("normalMap", WaterMgr->m_NormalMap[curTex]);
|
||||
if (WaterMgr->m_WaterBinormal)
|
||||
m->fancyWaterShader->BindTexture("normalMap2", WaterMgr->m_NormalMap[nexTex]);
|
||||
if (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves)
|
||||
{
|
||||
m->fancyWaterShader->BindTexture("Foam", WaterMgr->m_Foam);
|
||||
m->fancyWaterShader->BindTexture("heightmap", WaterMgr->m_HeightmapTexture);
|
||||
m->fancyWaterShader->BindTexture("infoTex", WaterMgr->m_OtherInfoTex);
|
||||
m->fancyWaterShader->Uniform("mapSize", (float)(WaterMgr->m_TexSize));
|
||||
}
|
||||
if (WaterMgr->m_WaterRealDepth)
|
||||
m->fancyWaterShader->BindTexture("depthTex", WaterMgr->m_depthTT);
|
||||
if (WaterMgr->m_WaterCoastalWaves)
|
||||
m->fancyWaterShader->BindTexture("waveTex", WaterMgr->m_waveTT);
|
||||
if (WaterMgr->m_WaterReflection)
|
||||
m->fancyWaterShader->BindTexture("reflectionMap", WaterMgr->m_ReflectionTexture);
|
||||
if (WaterMgr->m_WaterRefraction)
|
||||
m->fancyWaterShader->BindTexture("refractionMap", WaterMgr->m_RefractionTexture);
|
||||
|
||||
m->fancyWaterShader->BindTexture("losMap", losTexture.GetTextureSmooth());
|
||||
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
|
||||
|
||||
// TODO: only bind what's really needed for that.
|
||||
m->fancyWaterShader->Uniform("sunDir", lightEnv.GetSunDir());
|
||||
m->fancyWaterShader->Uniform("sunColor", lightEnv.m_SunColor.X);
|
||||
m->fancyWaterShader->Uniform("color", WaterMgr->m_WaterColor);
|
||||
@ -854,7 +868,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
|
||||
m->fancyWaterShader->Uniform("time", (float)time);
|
||||
m->fancyWaterShader->Uniform("screenSize", (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
|
||||
|
||||
if (shadow && superFancy)
|
||||
if (shadow && WaterMgr->m_WaterShadows)
|
||||
{
|
||||
m->fancyWaterShader->BindTexture("shadowTex", shadow->GetTexture());
|
||||
m->fancyWaterShader->Uniform("shadowTransform", shadow->GetTextureMatrix());
|
||||
@ -989,8 +1003,10 @@ void TerrainRenderer::RenderWater(const CShaderDefines& context, ShadowMap* shad
|
||||
{
|
||||
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
||||
|
||||
if (!WaterMgr->WillRenderFancyWater() || !RenderFancyWater(context, shadow))
|
||||
if (!WaterMgr->WillRenderFancyWater())
|
||||
RenderSimpleWater();
|
||||
else
|
||||
RenderFancyWater(context, shadow);
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderPriorities()
|
||||
|
@ -77,8 +77,19 @@ WaterManager::WaterManager()
|
||||
m_Heightmap = NULL;
|
||||
m_HeightmapTexture = 0;
|
||||
m_OtherInfoTex = NULL;
|
||||
m_RunningSuperFancy = WillRenderSuperFancyWater();
|
||||
|
||||
m_WaterNormal = false;
|
||||
m_WaterBinormal = false;
|
||||
m_WaterRealDepth = false;
|
||||
m_WaterFoam = false;
|
||||
m_WaterCoastalWaves = false;
|
||||
m_WaterRefraction = false;
|
||||
m_WaterReflection = false;
|
||||
m_WaterShadows = false;
|
||||
|
||||
m_NeedsReloading = false;
|
||||
m_NeedsFullReloading = false;
|
||||
m_TerrainChangeThisTurn = false;
|
||||
|
||||
m_VBWaves = NULL;
|
||||
m_VBWavesIndices = NULL;
|
||||
@ -269,84 +280,6 @@ void WaterManager::CreateSuperfancyInfo()
|
||||
waveForceHQ[j*mapSize + i] = 255 - color * 7;
|
||||
}
|
||||
}
|
||||
|
||||
// okay let's create the waves squares. i'll divide the map in arbitrary squares
|
||||
// For each of these squares, check if waves are needed.
|
||||
// If yes, look for the best positionning (in order to have a nice blending with the shore)
|
||||
// Then clean-up: remove squares that are too close to each other
|
||||
|
||||
std::vector<CVector2D> waveSquares;
|
||||
|
||||
int size = 8; // I think this is the size of the squares.
|
||||
for (int i = 0; i < mapSize/size; ++i)
|
||||
{
|
||||
for (int j = 0; j < mapSize/size; ++j)
|
||||
{
|
||||
|
||||
int landTexel = 0;
|
||||
int waterTexel = 0;
|
||||
CVector3D avnormal (0.0f,0.0f,0.0f);
|
||||
CVector2D landPosition(0.0f,0.0f);
|
||||
CVector2D waterPosition(0.0f,0.0f);
|
||||
for (int xx = 0; xx < size; ++xx)
|
||||
{
|
||||
for (int yy = 0; yy < size; ++yy)
|
||||
{
|
||||
if (terrain->GetVertexGroundLevel(i*size+xx,j*size+yy) > this->m_WaterHeight)
|
||||
{
|
||||
landTexel++;
|
||||
landPosition += CVector2D(i*size+xx,j*size+yy);
|
||||
}
|
||||
else
|
||||
{
|
||||
waterPosition += CVector2D(i*size+xx,j*size+yy);
|
||||
waterTexel++;
|
||||
}
|
||||
avnormal += terrain->CalcExactNormal( (i*size+xx)*4.0f,(j*size+yy)*4.0f);
|
||||
}
|
||||
}
|
||||
landPosition /= landTexel;
|
||||
waterPosition /= waterTexel;
|
||||
|
||||
avnormal[1] = 1.0f;
|
||||
avnormal.Normalize();
|
||||
avnormal[1] = 0.0f;
|
||||
|
||||
if (landTexel < size/2)
|
||||
continue;
|
||||
// this should help ensure that the shore is pretty flat.
|
||||
if (avnormal.Length() <= 0.2f)
|
||||
continue;
|
||||
|
||||
// To get the best position for squares, I start at the mean "ocean" position
|
||||
// And step by step go to the mean "land" position. I keep the position where I change from water to land.
|
||||
// If this never happens, the square is scrapped.
|
||||
if (terrain->GetExactGroundLevel(waterPosition.X*4.0f,waterPosition.Y*4.0f) > this->m_WaterHeight)
|
||||
continue;
|
||||
|
||||
CVector2D squarePos(-1,-1);
|
||||
for (u8 i = 0; i < 40; i++)
|
||||
{
|
||||
squarePos = landPosition * (i/40.0f) + waterPosition * (1.0f-(i/40.0f));
|
||||
if (terrain->GetExactGroundLevel(squarePos.X*4.0f,squarePos.Y*4.0f) > this->m_WaterHeight)
|
||||
break;
|
||||
}
|
||||
if (squarePos.X == -1)
|
||||
continue;
|
||||
|
||||
u8 enter = 1;
|
||||
// okaaaaaay. Got a square. Check for proximity.
|
||||
for (unsigned long i = 0; i < waveSquares.size(); i++)
|
||||
{
|
||||
if ( CVector2D(waveSquares[i]-squarePos).LengthSquared() < 100) {
|
||||
enter = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enter == 1)
|
||||
waveSquares.push_back(squarePos);
|
||||
}
|
||||
}
|
||||
// this creates information for waves and stores it in a texture.
|
||||
// texture "newHeightmap" is [x vector of wave direction, coefficient of "water raise", y vector of waves, distance to shore.]
|
||||
// texture "OtherInfo" stores the intensity of actual waves and of foam.
|
||||
@ -459,6 +392,86 @@ void WaterManager::CreateSuperfancyInfo()
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (this->m_WaterCoastalWaves)
|
||||
{
|
||||
// okay let's create the waves squares. i'll divide the map in arbitrary squares
|
||||
// For each of these squares, check if waves are needed.
|
||||
// If yes, look for the best positionning (in order to have a nice blending with the shore)
|
||||
// Then clean-up: remove squares that are too close to each other
|
||||
|
||||
std::vector<CVector2D> waveSquares;
|
||||
|
||||
int size = 8; // I think this is the size of the squares.
|
||||
for (int i = 0; i < mapSize/size; ++i)
|
||||
{
|
||||
for (int j = 0; j < mapSize/size; ++j)
|
||||
{
|
||||
|
||||
int landTexel = 0;
|
||||
int waterTexel = 0;
|
||||
CVector3D avnormal (0.0f,0.0f,0.0f);
|
||||
CVector2D landPosition(0.0f,0.0f);
|
||||
CVector2D waterPosition(0.0f,0.0f);
|
||||
for (int xx = 0; xx < size; ++xx)
|
||||
{
|
||||
for (int yy = 0; yy < size; ++yy)
|
||||
{
|
||||
if (terrain->GetVertexGroundLevel(i*size+xx,j*size+yy) > this->m_WaterHeight)
|
||||
{
|
||||
landTexel++;
|
||||
landPosition += CVector2D(i*size+xx,j*size+yy);
|
||||
}
|
||||
else
|
||||
{
|
||||
waterPosition += CVector2D(i*size+xx,j*size+yy);
|
||||
waterTexel++;
|
||||
}
|
||||
avnormal += terrain->CalcExactNormal( (i*size+xx)*4.0f,(j*size+yy)*4.0f);
|
||||
}
|
||||
}
|
||||
landPosition /= landTexel;
|
||||
waterPosition /= waterTexel;
|
||||
|
||||
avnormal[1] = 1.0f;
|
||||
avnormal.Normalize();
|
||||
avnormal[1] = 0.0f;
|
||||
|
||||
if (landTexel < size/2)
|
||||
continue;
|
||||
// this should help ensure that the shore is pretty flat.
|
||||
if (avnormal.Length() <= 0.2f)
|
||||
continue;
|
||||
|
||||
// To get the best position for squares, I start at the mean "ocean" position
|
||||
// And step by step go to the mean "land" position. I keep the position where I change from water to land.
|
||||
// If this never happens, the square is scrapped.
|
||||
if (terrain->GetExactGroundLevel(waterPosition.X*4.0f,waterPosition.Y*4.0f) > this->m_WaterHeight)
|
||||
continue;
|
||||
|
||||
CVector2D squarePos(-1,-1);
|
||||
for (u8 i = 0; i < 40; i++)
|
||||
{
|
||||
squarePos = landPosition * (i/40.0f) + waterPosition * (1.0f-(i/40.0f));
|
||||
if (terrain->GetExactGroundLevel(squarePos.X*4.0f,squarePos.Y*4.0f) > this->m_WaterHeight)
|
||||
break;
|
||||
}
|
||||
if (squarePos.X == -1)
|
||||
continue;
|
||||
|
||||
u8 enter = 1;
|
||||
// okaaaaaay. Got a square. Check for proximity.
|
||||
for (unsigned long i = 0; i < waveSquares.size(); i++)
|
||||
{
|
||||
if ( CVector2D(waveSquares[i]-squarePos).LengthSquared() < 100) {
|
||||
enter = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enter == 1)
|
||||
waveSquares.push_back(squarePos);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually create the waves' meshes.
|
||||
std::vector<SWavesVertex> waves_vertex_data;
|
||||
std::vector<GLushort> waves_indices;
|
||||
@ -527,14 +540,56 @@ void WaterManager::CreateSuperfancyInfo()
|
||||
// Construct indices buffer
|
||||
this->m_VBWavesIndices = g_VBMan.Allocate(sizeof(GLushort), waves_indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
|
||||
this->m_VBWavesIndices->m_Owner->UpdateChunkVertices(this->m_VBWavesIndices, &waves_indices[0]);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// This will set the bools properly
|
||||
void WaterManager::updateQuality()
|
||||
{
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERNORMAL) != m_WaterNormal) {
|
||||
m_WaterNormal = g_Renderer.GetOptionBool(CRenderer::OPT_WATERNORMAL);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERBINORMAL) != m_WaterBinormal) {
|
||||
m_WaterBinormal = g_Renderer.GetOptionBool(CRenderer::OPT_WATERBINORMAL);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERREALDEPTH) != m_WaterRealDepth) {
|
||||
m_WaterRealDepth = g_Renderer.GetOptionBool(CRenderer::OPT_WATERREALDEPTH);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERFOAM) != m_WaterFoam) {
|
||||
m_WaterFoam = g_Renderer.GetOptionBool(CRenderer::OPT_WATERFOAM);
|
||||
m_NeedsReloading = true;
|
||||
m_NeedsFullReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES) != m_WaterCoastalWaves) {
|
||||
m_WaterCoastalWaves = g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES);
|
||||
m_NeedsReloading = true;
|
||||
m_NeedsFullReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION) != m_WaterRefraction) {
|
||||
m_WaterRefraction = g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFLECTION) != m_WaterReflection) {
|
||||
m_WaterReflection = g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFLECTION);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERSHADOW) != m_WaterShadows) {
|
||||
m_WaterShadows = g_Renderer.GetOptionBool(CRenderer::OPT_WATERSHADOW);
|
||||
m_NeedsReloading = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool WaterManager::WillRenderFancyWater()
|
||||
{
|
||||
return (g_Renderer.GetCapabilities().m_FragmentShader && g_Renderer.GetOptionBool(CRenderer::OPT_FANCYWATER));
|
||||
if (!g_Renderer.GetCapabilities().m_FragmentShader)
|
||||
return false;
|
||||
if (g_Renderer.GetRenderPath() == 1)
|
||||
return false;
|
||||
if (!m_RenderWater)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool WaterManager::WillRenderSuperFancyWater()
|
||||
{
|
||||
return (WillRenderFancyWater() && g_Renderer.GetOptionBool(CRenderer::OPT_SUPERFANCYWATER));
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,23 @@ public:
|
||||
int m_WaterCurrentTex;
|
||||
CColor m_WaterColor;
|
||||
bool m_RenderWater;
|
||||
bool m_RunningSuperFancy;
|
||||
|
||||
// Those variables register the current quality level. If there is a change, I have to recompile the shader.
|
||||
bool m_WaterNormal;
|
||||
bool m_WaterBinormal;
|
||||
bool m_WaterRealDepth;
|
||||
bool m_WaterFoam;
|
||||
bool m_WaterCoastalWaves;
|
||||
bool m_WaterRefraction;
|
||||
bool m_WaterReflection;
|
||||
bool m_WaterShadows;
|
||||
|
||||
bool m_NeedsReloading;
|
||||
// requires also recreating the super fancy information.
|
||||
bool m_NeedsFullReloading;
|
||||
// used only by Atlas to know when to update the water map.
|
||||
bool m_TerrainChangeThisTurn;
|
||||
|
||||
bool m_WaterScroll;
|
||||
float m_WaterHeight;
|
||||
float m_WaterMaxAlpha;
|
||||
@ -131,17 +146,16 @@ public:
|
||||
*/
|
||||
void CreateSuperfancyInfo();
|
||||
|
||||
/**
|
||||
* Updates the settings to the one from the renderer, and sets m_NeedsReloading.
|
||||
*/
|
||||
void updateQuality();
|
||||
|
||||
/**
|
||||
* Returns true if fancy water shaders will be used (i.e. the hardware is capable
|
||||
* and it hasn't been configured off)
|
||||
*/
|
||||
bool WillRenderFancyWater();
|
||||
|
||||
/**
|
||||
* Returns true if super fancy water shaders will be used (i.e. the hardware is capable
|
||||
* and it hasn't been configured off)
|
||||
*/
|
||||
bool WillRenderSuperFancyWater();
|
||||
};
|
||||
|
||||
|
||||
|
@ -86,7 +86,6 @@ def report_performance(request):
|
||||
mapname = 'unknown' # e.g. random maps
|
||||
msecs = None
|
||||
shadows = False
|
||||
fancywater = False
|
||||
for name,table in json['profiler'].items():
|
||||
m = re.match(r'Profiling Information for: root \(Time in node: (\d+\.\d+) msec/frame\)', name)
|
||||
if m:
|
||||
@ -101,18 +100,11 @@ def report_performance(request):
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
if float(table['data']['render'][0]['render submissions'][0]['render reflections'][2]):
|
||||
fancywater = True
|
||||
except (KeyError, TypeError):
|
||||
pass
|
||||
|
||||
if msecs is None:
|
||||
return None
|
||||
|
||||
options = []
|
||||
if shadows: options.append('S')
|
||||
if fancywater: options.append('W')
|
||||
|
||||
return {
|
||||
'msecs': msecs,
|
||||
|
Loading…
Reference in New Issue
Block a user