Change the water texture to a new, bigger one, created in Blender (thanks to Enrique). Change settings so that they are more logical, yet allow reverting back to an even lower quality setting. Add a WIP high setting (with foam) which isn't finished yet.

Change the shader itself so that the effects look nicer and are more
consistent across settings.
Rework the water mesh generation (simpler system). Fix a few issues.

May work oddly with Atlas since I haven't been able to compile yet.

Refs #1875 (maybe fix), Fixes #2077 (I'll assume it does), Fixes #2114
(assumption again), refs #48.

This was SVN commit r15473.
This commit is contained in:
wraitii 2014-07-01 16:05:05 +00:00
parent 0bde61fa5b
commit ab30e0d4fb
90 changed files with 924 additions and 412 deletions

View file

@ -52,13 +52,12 @@ bpp = 0
; if false, actors won't be rendered but anything entity will be.
renderactors = true
waternormals = true
waterugly=false; Force usage of the fixed pipeline water. This is faster, but really, really ugly.
waterfancyeffects = false
waterrealdepth = true
waterfoam = false
watercoastalwaves = false
waterrefraction = true
waterreflection = true
watershadows = false
shadowsonwater = false
shadows = true
shadowpcf = true

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:700c9f9bb902ad9ebd312b677d469ccd7428ba0b45e85b84a19224deb4994b8f
size 133549

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:648aa9d384ce9940eacf8a15e2a3178426f359e2048f6faaf1dcaad93c8d8ee8
size 133841

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:95bc70b56e1515ba79e8c7fffada4059044a7d843df1821c0eae4383bad55d73
size 133865

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2c7c953293bcfa771d4913ad92703296103c63b15d7b2d6f6d47bc067c7c1795
size 133725

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:71ff3baedcbee953ae0e84fb28d317fcd272b9dd507c53c9944b88e1b8eefdbd
size 133281

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:457e27d5fa9cba41901add9b6ac1efcb670a9246e963a9c1b2a3efe7c63115dc
size 132947

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f3d91217613a2492d0ae2fceea766cc47bd5d462a504146f129e1183e528b795
size 132690

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dff254c330c1abb9c7b4dfa4b7d36e238889016beb9a812dd824cb3865f07b8f
size 132079

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9d87cecee12e037a18b5e060a7f2e7adbf3e4df113e7b27658800b724d8ff5d2
size 131590

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5af5ab5ec1322c8374e2eb1f3c240d928e3d02edb2bd26aae9b2a4fad22580d6
size 131082

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:25316348629268593e33d3389b6e4dd9ad8608322682cc8f0cb02b30abb30e15
size 130532

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4c9a5235a15cfe15acba1f5b52d51a9bcbdad65a966138b360e8a8abf45681dd
size 129997

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a153c65f80cd59f1accf7bd9e379f29c87de9cca0e5d90af40bce74591616e22
size 129613

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec8b586cc3f632e1945533b39af36f78075118aa4b451fc49e56b296cf4a7cf0
size 129151

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f0bdc29669f39cf9495bccb7be55d61e53eece4cbd20b82b76be52220537ed0c
size 128666

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8bf176acd29891d7e51f963eb5096260e640dfe3565c3f0d441841cbea0eb5f3
size 128316

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:556c9bd9e22e7735d2309ca654a6eaa51431988adbd51d7072833614d824178a
size 127820

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fdc699f62accaa85af3db147c1c216aaaf98cb185d8f5bc4df010014417c8b00
size 127542

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d778dbab2d245996df80a7692b2f281b6e1208a29e4011917d381b64442eda9e
size 127019

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ff4f420d62cc57081f9e0470ba20650197d1b519f85f757fa5caa6d9df6d7fc
size 126495

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:31541bfd8d10ef3a31d28b3dbb84339b35453672f5cd9e67f9c84727a931b218
size 126295

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6342914a1716652106002cb0fa882987a4fd8aa3bd14fdf34d785a6b5b75de2d
size 125836

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0f64c59ea4ec278b60b4a951d4b1633ade10b9f7f7d760e93b9d1fa0a1eea78a
size 125477

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9374ac12a24939220c7143bddfa4755cec228f70e6c0580daa4ca058205fcd4e
size 125126

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:964ae7a9b0d1cbb269c8f6f723d8fe0f1899a888b144cb245ca7587230556e25
size 124735

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a22a2b830c5ece9c0147501518b617a7ecb0eb803b60225092f7499faa880fe7
size 124469

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64e20b2bbc7d200a07a83d54f7680fdef5379c2178c2cea725b426bb8d02c0e2
size 124148

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:28e4f10ca364565b86af61b903a0d5a19fd899a4f4a6e7c44696cd3d2863a2dd
size 123847

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6a7ae0673a85477a8198cf644ff3832c986f3846231d1e4a28daf1adcdbf3eef
size 123577

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:566ece6fc8aa1a7fbce783eaec21e1feaaf909617535edabb8eef4ff044990bd
size 123470

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f5bcd8c353e515236d9398a44ad9f8dc354789ff74df97d5fd4ba755ad30d037
size 123393

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2cc5e95b9102dc24f7212dddc91262e9e6ce9538da5e9aa06913842ccbf5d719
size 123255

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dc027509fff17940b056912e5095cb06609da6e2e41dabe94beccdf6cceefeb6
size 123150

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0df3ea840898ab6e1871c49af353d63bcd2d137f987229416ac48a73b7851b82
size 123165

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f609ed6b89253a2f26f02f8bc440b91674b4667d0d8629c479f0bf7a0cd430f9
size 123374

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4499894b2219ed539052827128157e57d05a3be00817143019f6d7579db4d198
size 123299

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec31ea24489b54f2ba18739e63701b46ca3b533cbbbbe96593b3b2e77c030eb9
size 123517

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78d1c9fcb8d50a69c8fdb02e31ba46f33594ba31cb6e6a63245934f05789b5d2
size 123542

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:617365d3a13e92dbfca863ef1e3391535277ffa0347e2d40196317fa28b4b9f1
size 123720

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a44be3d1c907fc4ff1943ea1ab56b5c17c540ef98c71722d254dfae08a670b61
size 123949

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:55beb430a413ad6a5de0a037bdaf67e8272fa7411cbd168c50f945289f575fd5
size 124141

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b5efc9a2ddafc56aa18a6b6e42eb48ec765d2f80611fe602b7af22e0643da94
size 124638

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6f34b0592c923549d90b17319e3bba893a32836a2d817cde480e464edcc4469f
size 124857

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0a75c533a3b234eb82f71e52513cb0aa81e6a68852190d599eebf4baaaf95a4e
size 125207

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f28b57c4519d7aa69dbbdd61b679b6838643c70a659d545e0a52a8fed9daa766
size 125558

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5aa4204095f1c810ae4f5d2b72b5c6e53f58b3faaf0630f694100c19ea6338d7
size 125780

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1fb7f4a8018d52ee68123d845b61fe7f713c5f5cb40d817ea35aca428ddd85a1
size 126299

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2df68b1601d052422efc6b65d3505f1305e567a758514ffc8ebf8c7c08ffeed2
size 126545

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:023653d3e5017bddbaf03e4f2114c4bd6140f5543a6d14d38436ea61a6764704
size 127080

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:141698d3543e05b1b3877ecb27906b9ae0d8a59c9266fc13f15e66066b9d7ed3
size 127596

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:622fcab2239636da35c425ccd9ee0c03c15c497d935f853158a9becd61bc6332
size 128035

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:56aea8fac6ea600f35b8978db3cbc1e6fcc54a3fe595e17420dce83cc4244471
size 128627

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c80278c38888b26c3e78046f2b26311663cdc77d9ef9af3bd68798921fbfdcd7
size 129131

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd41eacb2cfea08e62da694489484bd599ebb87836c037f7af898d89d0fa946a
size 129822

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7d500b9990051e0819167f7bb0ac8f316d1119ca9a97ed59c0cbf2c74dad4acb
size 130572

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6670d3084efd0262398db459fbf537609bcfe39ed34b249e34ad87fc0923d071
size 131103

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ffb43052f90db2d43ad8fbb4051fbc9e6c1e82752ba7018062f173b8d36057f
size 131728

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7142860ee826dd5daabd8958a658a7d18bc61345c17a9d5e28f4ea84a19079df
size 132325

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b3832abd0da0d98c98601012f8c8125a6d8acd169ed2b7385d36d8ac9e8523da
size 133176

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:05f85ebc5ad515d208eb7c18a3bb9e067a468d563bb4407f25261721c8f94731
size 133792

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Textures>
<File pattern="normal*" normal="true" format="rgba" mipmap="true"/>
<File pattern="diffuse*" normal="false" format="rgba" mipmap="true"/>
</Textures>

View file

@ -21,13 +21,12 @@ var options = {
[translate("Smooth LOS"), translate("Lift darkness and fog-of-war smoothly (Requires Prefer GLSL)"), {"renderer":"SmoothLOS", "config":"smoothlos"}, "boolean"],
[translate("Unit Silhouettes"), translate("Show outlines of units behind buildings"), {"renderer":"Silhouettes", "config":"silhouettes"}, "boolean"],
[translate("Shadow Filtering"), translate("Smooth shadows"), {"renderer":"ShadowPCF", "config":"shadowpcf"}, "boolean"],
[translate("HQ Waviness"), translate("Use real normals for ocean-wave rendering, instead of applying them as a flat texture"), {"renderer":"WaterNormal", "config":"waternormals"}, "boolean"],
[translate("Fast & Ugly Water"), translate("Use the lowest settings possible to render water. This makes other settings irrelevant."), {"renderer":"WaterUgly", "config":"waterugly"}, "boolean"],
[translate("HQ Water Effects"), translate("Use higher-quality effects for water, rendering coastal waves, shore foam, and ships trails."), {"renderer":"WaterFancyEffects", "config":"waterfancyeffects"}, "boolean"],
[translate("Real Water Depth"), translate("Use actual water depth in rendering calculations"), {"renderer":"WaterRealDepth", "config":"waterrealdepth"}, "boolean"],
[translate("Water Reflections"), translate("Allow water to reflect a mirror image"), {"renderer":"WaterReflection", "config":"waterreflection"}, "boolean"],
[translate("Water Refraction"), translate("Use a real water refraction map and not transparency"), {"renderer":"WaterRefraction", "config":"waterrefraction"}, "boolean"],
[translate("Shore Foam"), translate("Show foam on water near shore depending on water waviness"), {"renderer":"WaterFoam", "config":"waterfoam"}, "boolean"],
[translate("Shore Waves"), translate("Show breaking waves on water near shore (Requires HQ Waviness)"), {"renderer":"WaterCoastalWaves", "config":"watercoastalwaves"}, "boolean"],
[translate("Water Shadows"), translate("Cast shadows on water"), {"renderer":"WaterShadow", "config":"watershadows"}, "boolean"],
[translate("Shadows on Water"), translate("Cast shadows on water"), {"renderer":"WaterShadows", "config":"watershadows"}, "boolean"],
[translate("VSync"), translate("Run vertical sync to fix screen tearing. REQUIRES GAME RESTART"), {"config":"vsync"}, "boolean"],
],
"soundSetting":

View file

@ -180,7 +180,6 @@ function RunDetection(settings)
var disable_shadowpcf = undefined;
var disable_allwater = undefined;
var disable_fancywater = undefined;
var disable_fbowater = undefined;
var override_renderpath = undefined;
// TODO: add some mechanism for setting config values
@ -257,7 +256,6 @@ function RunDetection(settings)
{
disable_allwater = false;
disable_fancywater = true;
//disable_fbowater = true;
disable_shadowpcf = true;
}
@ -295,7 +293,6 @@ function RunDetection(settings)
"disable_shadowpcf": disable_shadowpcf,
"disable_allwater": disable_allwater,
"disable_fancywater": disable_fancywater,
"disable_fbowater": disable_fbowater,
"override_renderpath": override_renderpath,
};
}
@ -334,9 +331,6 @@ global.RunHardwareDetection = function(settings)
if (output.disable_fancywater !== undefined)
Engine.SetDisableFancyWater(output.disable_fancywater);
if (output.disable_fbowater !== undefined)
Engine.SetDisableFancyWater(output.disable_fbowater);
if (output.override_renderpath !== undefined)
Engine.SetRenderPath(output.override_renderpath);

View file

@ -29,7 +29,7 @@ for each (var settings in hwdetectTestData)
var os = (settings.os_linux ? "linux" : settings.os_macosx ? "macosx" : settings.os_win ? "win" : "???");
var disabled = [];
for each (var d in ["disable_audio", "disable_s3tc", "disable_shadows", "disable_shadowpcf", "disable_allwater", "disable_fbowater", "disable_fancywater", "override_renderpath"])
for each (var d in ["disable_audio", "disable_s3tc", "disable_shadows", "disable_shadowpcf", "disable_allwater", "disable_fancywater", "override_renderpath"])
if (output[d] !== undefined)
disabled.push(d+"="+output[d])

View file

@ -35,6 +35,7 @@ uniform vec3 fogColor;
uniform vec2 fogParams;
varying vec4 v_lighting;
varying vec4 v_lighting2;
varying vec2 v_tex;
varying vec2 v_los;
@ -249,9 +250,12 @@ void main()
specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow);
#endif
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * get_shadow();
vec3 ambColor = texdiffuse * ambient;
float shadow = get_shadow();
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * shadow;
vec3 ambColor = texdiffuse * (ambient + v_lighting2.rgb*(shadow+0.8)*0.5);
//ambColor = texdiffuse * ambient;
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
vec3 ao = texture2D(aoTex, v_tex2).rrr;
ao = mix(vec3(1.0), ao * 2.0, effectSettings.w);
@ -273,6 +277,8 @@ void main()
#endif
color *= shadingColor;
//color = v_lighting2.rgb;
gl_FragColor.rgb = color;
}

View file

@ -23,6 +23,7 @@ uniform mat4 instancingTransform;
#endif
varying vec4 v_lighting;
varying vec4 v_lighting2;
varying vec2 v_tex;
varying vec2 v_los;
@ -74,6 +75,8 @@ vec4 fakeCos(vec4 x)
void main()
{
// Compute position, normal and tangent vertices.
// GPU skinning does the animation live on the GPU.
#if USE_GPU_SKINNING
vec3 p = vec3(0.0);
vec3 n = vec3(0.0);
@ -105,7 +108,7 @@ void main()
#endif
#endif
// Calculate swaying of trees dynamically
#if USE_WIND
vec2 wind = windData.xy;
@ -139,7 +142,6 @@ void main()
position.xz += diff + diff2 * wind;
#endif
gl_Position = transform * position;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX_MAP
@ -165,7 +167,12 @@ void main()
#endif
#endif
v_lighting.xyz = max(0.0, dot(normal, -sunDir)) * sunColor;
float firstDot = dot(normal, -sunDir);
v_lighting2.xyz = max(0.0, (dot(normal, vec3(-sunDir.r,sunDir.g,-sunDir.b)) + 1.0) - abs(firstDot)*0.8 - max(0.0,firstDot)*1.9) * 0.4 * sunColor;
v_lighting2 -= a_vertex.y*0.1;
v_lighting2 = clamp(vec4(0.3), vec4(0.0), v_lighting2);
v_lighting.xyz = max(0.0, firstDot) * sunColor;
v_tex = a_uv0;
@ -177,7 +184,7 @@ void main()
v_shadow = shadowTransform * position;
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
v_shadow.xy *= shadowScale.xy;
#endif
#endif
#endif
v_los = position.xz * losTransform.x + losTransform.y;

View file

@ -0,0 +1,52 @@
#version 110
// This is a lightened version of water_high.fs that generates only the "n" vector (ie the normal) and the foam coverage.
// It's thus uncommented.
uniform float waviness;
uniform vec2 screenSize;
uniform float time;
varying vec3 worldPos;
uniform float mapSize;
uniform sampler2D normalMap;
uniform sampler2D normalMap2;
/*#if USE_FOAM || USE_WAVES
uniform sampler2D Foam;
uniform sampler2D waveTex;
#endif*/
void main()
{
float wavyFactor = waviness * 0.125;
vec3 ww1 = texture2D(normalMap, (gl_TexCoord[0].st) * (0.7 - waviness/20.0)).xzy;
vec3 ww2 = texture2D(normalMap2, (gl_TexCoord[0].st) * (0.7 - waviness/20.0)).xzy;
//vec3 smallWW = texture2D(normalMap, (gl_TexCoord[0].st - gl_TexCoord[0].wz*6.0) * 1.2).xzy;
//vec3 smallWW2 = texture2D(normalMap2, (gl_TexCoord[0].st - gl_TexCoord[0].wz*6.0) * 1.2).xzy;
ww1 = mix(ww1, ww2, mod(time * 60.0, 8.0) / 8.0);
//smallWW = mix(smallWW, smallWW2, mod(time * 60.0, 8.0) / 8.0) - vec3(0.5);
//ww += vec3(smallWW.x,0.0,smallWW.z)*0.5;
/*#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*/
vec3 n = normalize(ww1 - vec3(0.5, 0.5, 0.5));
n = mix(vec3(0.0,1.0,0.0),n,waviness/10.0);
float foamFact1 = texture2D(normalMap, (gl_TexCoord[0].st) * 0.3).a;
float foamFact2 = texture2D(normalMap2, (gl_TexCoord[0].st) * 0.3).a;
float foamFact = mix(foamFact1, foamFact2, mod(time * 60.0, 8.0) / 8.0);
float foamUniversal1 = texture2D(normalMap, (gl_TexCoord[0].st) * 0.05).a;
float foamUniversal2 = texture2D(normalMap2, (gl_TexCoord[0].st) * 0.05).a;
float foamUniversal = mix(foamUniversal1, foamUniversal2, mod(time * 60.0, 8.0) / 8.0);
gl_FragColor.rgba = vec4(n,foamFact*foamUniversal*30.0);
}

View file

@ -0,0 +1,22 @@
#version 110
// This is a lightened version of water_high.vs
uniform float repeatScale;
uniform vec2 translation;
uniform float time;
uniform float mapSize;
varying vec3 worldPos;
attribute vec3 a_vertex;
void main()
{
worldPos = a_vertex;
gl_TexCoord[0] = vec4(a_vertex.xz*repeatScale,translation);
gl_TexCoord[3].zw = vec2(a_vertex.xz)/mapSize;
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_vertex, 1.0);
}

View file

@ -1,13 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<program type="glsl">
<vertex file="glsl/waves.vs">
<vertex file="glsl/water_effects.vs">
<stream name="pos"/>
<stream name="uv0"/>
<stream name="color"/>
<attrib name="a_vertex" semantics="gl_Vertex"/>
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
</vertex>
<fragment file="glsl/waves.fs"/>
<fragment file="glsl/water_effects.fs"/>
</program>

View file

@ -23,11 +23,17 @@ varying vec3 worldPos;
varying float waterDepth;
varying vec4 waterInfo;
uniform float mapSize;
uniform samplerCube skyCube;
uniform sampler2D normalMap;
uniform sampler2D normalMap2;
#if USE_FANCY_EFFECTS
uniform sampler2D waterEffectsTex;
#endif
#if USE_REFLECTION
uniform sampler2D reflectionMap;
#endif
@ -37,11 +43,13 @@ uniform sampler2D normalMap2;
#if USE_REAL_DEPTH
uniform sampler2D depthTex;
#endif
#if USE_FOAM || USE_WAVES
/*#if USE_FOAM || USE_WAVES
uniform sampler2D Foam;
uniform sampler2D waveTex;
#endif
#if USE_SHADOWS && USE_SHADOW
#endif*/
#if USE_SHADOWS_ON_WATER && USE_SHADOW
varying vec4 v_shadow;
#if USE_SHADOW_SAMPLER
uniform sampler2DShadow shadowTex;
@ -53,7 +61,7 @@ uniform sampler2D normalMap2;
#endif
float get_shadow(vec4 coords)
{
#if USE_SHADOWS && !DISABLE_RECEIVE_SHADOWS
#if USE_SHADOWS_ON_WATER && !DISABLE_RECEIVE_SHADOWS
#if USE_SHADOW_SAMPLER
#if USE_SHADOW_PCF
vec2 offset = fract(coords.xy - 0.5);
@ -78,6 +86,31 @@ uniform sampler2D normalMap2;
}
#endif
// TODO: convert this to something not only for AABBs
struct Ray {
vec3 Origin;
vec3 Direction;
};
float IntersectBox (in Ray ray, in vec3 minimum, in vec3 maximum)
{
vec3 OMIN = ( minimum - ray.Origin ) / ray.Direction;
vec3 OMAX = ( maximum - ray.Origin ) / ray.Direction;
vec3 MAX = max ( OMAX, OMIN );
return min ( MAX.x, min ( MAX.y, MAX.z ) );
}
// This is sorta useless since it's hardcoded for 45°. Change it to sun orientation too.
mat3 rotationMatrix()
{
vec3 axis = vec3(0.0,1.0,0.0);
float s = sin(1.12);
float c = cos(1.12);
return mat3(c, 0.0, s,
0.0, 1.0, 0.0,
-s, 0.0, c);
}
vec3 get_fog(vec3 color)
{
float density = fogParams.x;
@ -96,50 +129,63 @@ vec3 get_fog(vec3 color)
void main()
{
#if USE_FOAM || USE_WAVES
vec4 heightmapval = waterInfo;
vec2 beachOrientation = heightmapval.rg;
float distToShore = heightmapval.b;
#endif
vec3 n, l, h, v; // Normal, light vector, half-vector and view vector (vector to eye)
float ndotl, ndoth, ndotv;
//float fwaviness = 1;
float fresnel;
float t; // Temporary variable
vec2 reflCoords, refrCoords;
vec3 reflColor, refrColor, specular;
float losMod;
// Correct the waviness (range [0,10]) to something slightly more convenient (range [0,1.2] so you can treat it like [0.1] with overdraft).
float wavyFactor = waviness * 0.125;
l = -sunDir;
v = normalize(cameraPos - worldPos);
h = normalize(l + v);
// 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_NORMALS
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);
vec3 l = -sunDir;
vec3 v = normalize(cameraPos - worldPos);
vec3 h = normalize(l + v);
#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
ndoth = dot( mix(vec3(0.0,1.0,0.0),n,clamp(wavyFactor * v.y * 8.0,0.05,1.0)) ,h);
n = mix(vec3(0.0,1.0,0.0),n,wavyFactor);
#else
ndoth = dot(vec3(0.0,1.0,0.0), h);
n = vec3(0.0,1.0,0.0);
#endif
// Calculate water normals.
ndotl = (dot(n, l) + 1.0)/2.0;
ndotv = clamp(dot(n, v),0.0,1.0);
#if USE_FANCY_EFFECTS
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy/screenSize);
vec3 n = fancyeffects.rgb;
#else
// This method uses 60 animated water frames. We're blending between each two frames
// TODO: could probably have fewer frames thanks to this blending.
// Scale the normal textures by waviness so that big waviness means bigger waves.
vec3 ww1 = texture2D(normalMap, (gl_TexCoord[0].st) * (0.7 - waviness/20.0)).xzy;
vec3 ww2 = texture2D(normalMap2, (gl_TexCoord[0].st) * (0.7 - waviness/20.0)).xzy;
//vec3 smallWW = texture2D(normalMap, (gl_TexCoord[0].st - gl_TexCoord[0].wz*6.0) * 1.2).xzy;
//vec3 smallWW2 = texture2D(normalMap2, (gl_TexCoord[0].st - gl_TexCoord[0].wz*6.0) * 1.2).xzy;
ww1 = mix(ww1, ww2, mod(time * 60.0, 8.0) / 8.0);
//smallWW = mix(smallWW, smallWW2, mod(time * 60.0, 8.0) / 8.0) - vec3(0.5);
//ww += vec3(smallWW.x,0.0,smallWW.z)*0.5;
/*#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*/
// Fix our normals.
vec3 n = normalize(ww1 - vec3(0.5, 0.5, 0.5));
// Flatten them based on waviness.
n = mix(vec3(0.0,1.0,0.0),n,waviness/10.0);
#endif
// simulates how parallel the "point->sun", "view->point" vectors are.
// To always have a bit of that, we don't use the "n" we calculated above.
float ndoth = dot( mix(vec3(0.0,1.0,0.0),n,0.1 + min(0.8,waviness*waviness/70.0)) , h);
// how perpendicular to the normal our view is. Used for fresnel.
float ndotv = clamp(dot(n, v),0.0,1.0);
// diffuse lighting-like. used for shadows?
float ndotl = (dot(n, l) + 1.0)/2.0;
float depth;
#if USE_REAL_DEPTH
// Don't change these two. They should match the values in the config (TODO: dec uniforms).
float zNear = 2.0;
@ -167,17 +213,25 @@ void main()
if (z_b < undisto_z_b)
z_b = undisto_z_b;
float z_n = 2.0 * z_b - 1.0;
float waterDepth2 = (2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)) - waterDBuffer);
float distoFactor = clamp(waterDepth2/3.0,0.0,7.0);
depth = (2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)) - waterDBuffer);
#else
float perceivedDepth = waterDepth / (v.y*v.y);
float distoFactor = clamp(perceivedDepth/4.0,0.0,7.0);
depth = waterDepth / (min(0.5,v.y)*1.5*min(0.5,v.y)*2.0);
#endif
fresnel = pow(1.05 - ndotv, 1.3333); // approximation. I'm using 1.05 and not 1.0 because it causes artifacts, see #1714
// Fresnel for "how much reflection vs how much refraction".
// Since we're not trying to simulate a realistic ocean 100%, aim for something that gives a little too much reflection
// because we're not used to seeing the see from above.
fresnel = clamp(pow(1.05 - ndotv, 1.3),0.0,0.8); // approximation. I'm using 1.05 and not 1.0 because it causes artifacts, see #1714
// multiply by v.y so that in the distance refraction wins.
// TODO: this is a hack because reflections don't work in the distance.
fresnel *= min(1.0,log(1.0 + v.y*5.0));
fresnel = 0.2 + fresnel * 0.8;
#if USE_FOAM
//gl_FragColor = vec4(fresnel,fresnel,fresnel,1.0);
//return;
/*#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.
@ -196,120 +250,115 @@ void main()
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
#endif*/
#if USE_SHADOWS && USE_SHADOW
#if USE_SHADOWS_ON_WATER && USE_SHADOW
float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw));
#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".
// And it looks weird (again, we are not used to seeing water from above).
float fixedVy = clamp(v.y,0.1,1.0);
float distoFactor = clamp(depth/2.0,0.0,7.0);
float murky = mix(200.0,0.1,pow(murkiness,0.25));
#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
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);
#if USE_SHADOWS && USE_SHADOW
refrColor = (0.5 + 0.5*ndotl) * mix(color * (0.5 + shadow/2.0),mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
#else
refrColor = (0.5 + 0.5*ndotl) * mix(color,mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
#endif
refrCoords = clamp( (0.5*gl_TexCoord[2].xy - n.xz * distoFactor*10.0) / gl_TexCoord[2].w + 0.5,0.0,1.0); // Unbias texture coords
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
// TODO: make murkiness (both types rematter on that.
// linearly extinct the water. This is how quickly we see nothing but the pure water color
float extFact = max(0.0,1.0 - (depth*fixedVy/murky));
// This is how tinted the water is, ie how quickly the refracted floor takes the tint of the water
float ColextFact = max(0.0,1.0 - (depth*fixedVy/murky));
vec3 colll = mix(refColor*tint,refColor,ColextFact);
#if USE_SHADOWS_ON_WATER && USE_SHADOW
// TODO:
refrColor = mix(color, colll, extFact);
#else
refrCoords = clamp( (0.5*gl_TexCoord[2].xy - n.xz * distoFactor) / gl_TexCoord[2].w + 0.5,0.0,1.0); // Unbias texture coords
// cleverly get the perceived depth based on camera tilting (if horizontal, it's likely we will have more water to look at).
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
float luminance = (1.0 - clamp((perceivedDepth/mix(300.0,1.0, pow(murkiness,0.2) )), 0.0, 1.0));
float colorExtinction = clamp(perceivedDepth*murkiness/5.0,0.0,1.0);
#if USE_SHADOWS && USE_SHADOW
refrColor = (0.5 + 0.5*ndotl) * mix(color * (0.5 + shadow/2.0),mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
#else
refrColor = (0.5 + 0.5*ndotl) * mix(color,mix(refColor,refColor*tint,colorExtinction),luminance*luminance);
#endif
refrColor = mix(color, colll, extFact);
#endif
#else
float alphaCoeff = 0.0;
#if USE_REAL_DEPTH
float luminance = clamp((waterDepth2/mix(150.0,2.0, pow(murkiness,0.2) )), 0.0, 1.0);
alphaCoeff = mix(mix(0.0,3.0 - (tint.r + tint.g + tint.b),clamp(waterDepth2*murkiness/5.0,0.0,1.0)),1.0,luminance*luminance);
#else
float luminance = clamp(((waterDepth / v.y)/mix(150.0,2.0, pow(murkiness,0.2) )), 0.0, 1.0);
alphaCoeff = mix(mix(0.0,3.0 - (tint.r + tint.g + tint.b),clamp(perceivedDepth*murkiness/5.0,0.0,1.0)),1.0,luminance*luminance);
#endif
// linearly extinct the water. This is how quickly we see nothing but the pure water color
float extFact = max(0.0,1.0 - (depth*fixedVy/20.0));
// using both those factors, get our transparency.
// This will be our base transparency on top.
float base = 0.4 + depth*fixedVy/15.0; // TODO: murkiness.
float alphaCoeff = mix(1.0, base, extFact);
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 + distoFactor*1.5*n.xz) / gl_TexCoord[1].w + 0.5,0.0,1.0); // Unbias texture coords
reflCoords = clamp( (0.5*gl_TexCoord[1].xy - waviness * 2.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);
// TODO: At very low angles the reflection stuff doesn't really work any more:
// IRL you would get a blur of the sky, but we don't have that precision (would require mad oversampling)
// So tend towards a predefined color (per-map) which looks like what the skybox would look like if you really blurred it.
// The TODO here would be to precompute a band (1x32?) that represents the average color around the map.
// TODO: another issue is that at high distances (half map) the texture blurs into flatness. Using better mipmaps won't really solve it
// So we'll need to stop showing reflections and default to sky color there too.
// Unless maybe waviness is so low that you would see like in a mirror anyways.
//float disttt = distance(worldPos,cameraPos);
//reflColor = mix(vec3(0.5,0.5,0.55), reflColor, clamp(1.0-disttt/600.0*disttt/600.0,0.0,1.0));//clamp(-0.05 + v.y*20.0,0.0,1.0));
#else
vec3 eye = reflect(v, mix(vec3(0.0,1.0,0.0),n,0.2));
vec3 tex = textureCube(skyCube, eye).rgb;
vec3 eye = reflect(v,n);
eye.y = min(-0.1,eye.y);
// let's calculate where we intersect with the skycube.
Ray myRay = Ray(vec3(worldPos.x/4.0,worldPos.y,worldPos.z/4.0),eye);
vec3 start = vec3(-1500.0 + mapSize/2.0,-100.0,-1500.0 + mapSize/2.0);
vec3 end = vec3(1500.0 + mapSize/2.0,500.0,1500.0 + mapSize/2.0);
float tmin = IntersectBox(myRay,start,end);
vec3 newpos = vec3(-worldPos.x/4.0,worldPos.y,-worldPos.z/4.0) + eye * tmin - vec3(-mapSize/2.0,worldPos.y,-mapSize/2.0);
//newpos = normalize(newpos);
newpos.y *= 6.0;
newpos *= rotationMatrix();
vec3 tex = textureCube(skyCube, newpos).rgb;
//float disttt = distance(worldPos,cameraPos);
//tex = mix(tex,vec3(0.7,0.7,0.9),clamp(disttt/300.0*disttt/300.0*disttt/300.0,0.0,0.9));
//gl_FragColor = vec4(clamp(disttt/300.0*disttt/300.0,0.0,1.0),clamp(disttt/300.0*disttt/300.0,0.0,1.0),clamp(disttt/300.0*disttt/300.0,0.0,1.0),1.0);
//return;
reflColor = mix(tex, sunColor * reflectionTint, reflectionTintStrength);
#endif
#if USE_NORMALS
specular = pow(ndoth, mix(100.0,450.0, v.y*2.0)) * sunColor * 1.5;
#else
specular = pow(ndoth, mix(100.0,450.0, v.y*2.0)) * sunColor * 1.5 * ww.r;
#endif
// Specular.
specular = pow(ndoth, mix(100.0,450.0, v.y*2.0))*sunColor * 1.5;// * sunColor * 1.5 * ww.r;
losMod = texture2D(losMap, gl_TexCoord[3].st).a;
losMod = losMod < 0.03 ? 0.0 : losMod;
vec3 colour;
#if USE_SHADOWS && USE_SHADOW
#if USE_SHADOWS_ON_WATER && USE_SHADOW
float fresShadow = mix(fresnel, fresnel*shadow, 0.05 + murkiness*0.2);
#if USE_FOAM
/* #if USE_FOAM
colour = mix(refrColor, reflColor, fresShadow) + max(ndotl,0.4)*(finalFoam)*(shadow/2.0 + 0.5);
#else
colour = mix(refrColor, reflColor, fresShadow);
#endif
#else*/
colour = mix(refrColor, reflColor, fresShadow);
#else
#if USE_FOAM
/*#if USE_FOAM
colour = mix(refrColor, reflColor, fresnel) + max(ndotl,0.4)*(finalFoam);
#else
colour = mix(refrColor, reflColor, fresnel);
#endif
#else*/
colour = mix(refrColor, reflColor, fresnel);
#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
#endif
#if USE_SHADOWS && USE_SHADOW
#if USE_SHADOWS_ON_WATER && USE_SHADOW
colour += shadow*specular;
#else
colour += specular;
#endif
gl_FragColor.rgb = get_fog(colour) * 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;
// TODO: work the foam in somewhere else.
#if USE_FANCY_EFFECTS
gl_FragColor.rgb = get_fog(colour) * losMod + fancyeffects.a * losMod;
#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 = 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
gl_FragColor.rgb = get_fog(colour) * losMod;
#endif
#if !USE_REFRACTION
gl_FragColor.a = clamp(depth*2.0,0.0,1.0) * alphaCoeff;
#else
gl_FragColor.a = clamp(depth*2.0,0.0,1.0);
#endif
}

View file

@ -18,7 +18,8 @@ uniform float mapSize;
varying vec3 worldPos;
varying float waterDepth;
varying vec4 waterInfo;
#if USE_SHADOW && USE_SHADOWS
#if USE_SHADOW && USE_SHADOWS_ON_WATER
varying vec4 v_shadow;
#endif
attribute vec3 a_vertex;
@ -37,7 +38,7 @@ void main()
gl_TexCoord[3].zw = vec2(a_vertex.xz)/mapSize;
#if USE_SHADOW && USE_SHADOWS
#if USE_SHADOW && USE_SHADOWS_ON_WATER
v_shadow = shadowTransform * vec4(a_vertex, 1.0);
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
v_shadow.xy *= shadowScale.xy;

View file

@ -1,24 +0,0 @@
#version 110
uniform sampler2D waveTex;
uniform sampler2D infoTex;
uniform float time;
uniform float waviness;
void main()
{
vec3 color = texture2D(waveTex, gl_TexCoord[0].st * vec2(2.0,4.0) - vec2(0.0,0.5 + time/5.0)).rgb;
float split = abs(gl_TexCoord[0].x - 0.5);
split = 0.48 - split;
split *= 3.0;
split = min(1.0,split);
float opac = split*min(1.0, gl_TexCoord[0].y);
opac *= 1.0 - max(0.0,gl_TexCoord[0].y-0.9)*10.0;
color = mix(vec3(0.5,0.5,1.0),color, opac);
gl_FragColor.rgb = mix(vec3(0.5,0.5,1.0), color, clamp(texture2D(infoTex,gl_TexCoord[0].zw).r,0.4,1.0));
gl_FragColor.a = 1.0;
}

View file

@ -1,13 +0,0 @@
#version 110
attribute vec3 a_vertex;
attribute vec2 a_uv0;
uniform float mapSize;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_vertex, 1.0);
gl_TexCoord[0].st = a_uv0;
gl_TexCoord[0].zw = vec2(a_vertex.xz)/mapSize;
}

View file

@ -1 +1 @@
L"custom build"
L"-release"

View file

@ -50,7 +50,7 @@ X(MODE_WIREFRAME)
X(SYS_HAS_ARB)
X(SYS_HAS_GLSL)
X(SYS_PREFER_GLSL)
X(USE_FOAM)
X(USE_FANCY_EFFECTS)
X(USE_FP_SHADOW)
X(USE_GPU_SKINNING)
X(USE_INSTANCING)
@ -60,10 +60,9 @@ X(USE_REAL_DEPTH)
X(USE_REFLECTION)
X(USE_REFRACTION)
X(USE_SHADOW)
X(USE_SHADOWS)
X(USE_SHADOWS_ON_WATER)
X(USE_SHADOW_PCF)
X(USE_SHADOW_SAMPLER)
X(USE_WAVES)
X2(_emptystring, "")
X(a_skinJoints)
X(a_skinWeights)
@ -142,7 +141,7 @@ X(tint)
X(transform)
X(translation)
X(waterTex)
X(waveTex)
X(waterEffectsTex)
X(waviness)
X(width)
X(zFar)

View file

@ -41,10 +41,9 @@ bool g_RenderActors = true;
bool g_Shadows = false;
bool g_ShadowPCF = false;
bool g_WaterNormal = false;
bool g_WaterUgly = false;
bool g_WaterFancyEffects = 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;
@ -94,15 +93,12 @@ static void LoadGlobals()
CFG_GET_VAL("shadows", Bool, g_Shadows);
CFG_GET_VAL("shadowpcf", Bool, g_ShadowPCF);
CFG_GET_VAL("waternormals",Bool, g_WaterNormal);
CFG_GET_VAL("waterugly",Bool, g_WaterUgly);
CFG_GET_VAL("waterfancyeffects",Bool, g_WaterFancyEffects);
CFG_GET_VAL("waterrealdepth",Bool, g_WaterRealDepth);
CFG_GET_VAL("waterfoam",Bool, g_WaterFoam);
CFG_GET_VAL("watercoastalwaves",Bool, g_WaterCoastalWaves);
if (g_WaterCoastalWaves && !g_WaterNormal)
g_WaterCoastalWaves = false;
CFG_GET_VAL("waterrefraction",Bool, g_WaterRefraction);
CFG_GET_VAL("waterreflection",Bool, g_WaterReflection);
CFG_GET_VAL("watershadows",Bool, g_WaterShadows);
CFG_GET_VAL("shadowsonwater",Bool, g_WaterShadows);
CFG_GET_VAL("renderpath", String, g_RenderPath);
CFG_GET_VAL("particles", Bool, g_Particles);

View file

@ -50,14 +50,12 @@ extern bool g_RenderActors;
// flag to switch on shadows
extern bool g_Shadows;
// Use real normals for ocean-wave rendering, instead of applying them as a flat texture.
extern bool g_WaterNormal;
// Force the use of the fixed function for rendering water.
extern bool g_WaterUgly;
// Add foam and waves near the shores, trails following ships, and other HQ things.
extern bool g_WaterFancyEffects;
// 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.

View file

@ -591,13 +591,12 @@ static void InitRenderer()
g_Renderer.SetOptionBool(CRenderer::OPT_NOVBO, g_NoGLVBO);
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWS, g_Shadows);
g_Renderer.SetOptionBool(CRenderer::OPT_WATERNORMAL, g_WaterNormal);
g_Renderer.SetOptionBool(CRenderer::OPT_WATERUGLY, g_WaterUgly);
g_Renderer.SetOptionBool(CRenderer::OPT_WATERFANCYEFFECTS, g_WaterFancyEffects);
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_WaterReflection);
g_Renderer.SetOptionBool(CRenderer::OPT_WATERREFRACTION, g_WaterRefraction);
g_Renderer.SetOptionBool(CRenderer::OPT_WATERSHADOW, g_WaterShadows);
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWSONWATER, g_WaterShadows);
g_Renderer.SetRenderPath(CRenderer::GetRenderPathByName(g_RenderPath));
g_Renderer.SetOptionBool(CRenderer::OPT_SHADOWPCF, g_ShadowPCF);

View file

@ -147,39 +147,28 @@ void SetDisableShadowPCF(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool di
void SetDisableAllWater(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool disabled)
{
if (!IsOverridden("waternormals"))
g_WaterNormal = !disabled;
g_WaterUgly = true;
if (!IsOverridden("waterfancyeffects"))
g_WaterFancyEffects = !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"))
if (!IsOverridden("shadowsonwater"))
g_WaterShadows = !disabled;
}
void SetDisableFancyWater(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool disabled)
{
if (!IsOverridden("waterfancyeffects"))
g_WaterFancyEffects = !disabled;
if (!IsOverridden("waterrealdepth"))
g_WaterRealDepth = !disabled;
if (!IsOverridden("waterfoam"))
g_WaterFoam = !disabled;
if (!IsOverridden("watercoastalwaves"))
g_WaterCoastalWaves = !disabled;
if (!IsOverridden("watershadows"))
if (!IsOverridden("shadowsonwater"))
g_WaterShadows = !disabled;
}
void SetDisableFBOWater(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), bool disabled)
{
if (!IsOverridden("waterfoam"))
g_WaterFoam = !disabled;
if (!IsOverridden("watercoastalwaves"))
g_WaterCoastalWaves = !disabled;
}
void SetRenderPath(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string renderpath)
{
@ -198,7 +187,6 @@ void RunHardwareDetection()
scriptInterface.RegisterFunction<void, bool, &SetDisableShadowPCF>("SetDisableShadowPCF");
scriptInterface.RegisterFunction<void, bool, &SetDisableAllWater>("SetDisableAllWater");
scriptInterface.RegisterFunction<void, bool, &SetDisableFancyWater>("SetDisableFancyWater");
scriptInterface.RegisterFunction<void, bool, &SetDisableFBOWater>("SetDisableFBOWater");
scriptInterface.RegisterFunction<void, std::string, &SetRenderPath>("SetRenderPath");
// Load the detection script:

View file

@ -1305,31 +1305,168 @@ void CPatchRData::BuildWater()
// TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
if (WaterMgr->m_NeedInfoUpdate)
/*if (WaterMgr->m_NeedInfoUpdate)
{
WaterMgr->m_NeedInfoUpdate = false;
WaterMgr->CreateSuperfancyInfo(m_Simulation);
}
}*/
CPatch* patch = m_Patch;
CTerrain* terrain = patch->m_Parent;
ssize_t mapSize = (size_t)terrain->GetVerticesPerSide();
//Top-left coordinates of our patch.
ssize_t x1 = m_Patch->m_X*PATCH_SIZE;
ssize_t z1 = m_Patch->m_Z*PATCH_SIZE;
// to whoever implements different water heights, this is a TODO: water height)
float waterHeight = cmpWaterManager->GetExactWaterLevel(0.0f,0.0f);
int moves[4][2] = { {0,0}, {water_cell_size,0}, {0,water_cell_size}, {water_cell_size,water_cell_size} };
// build vertices, uv, and shader varying
for (ssize_t z = 0; z < PATCH_SIZE; z += water_cell_size)
{
for (ssize_t x = 0; x <= PATCH_SIZE; x += water_cell_size)
for (ssize_t x = 0; x < PATCH_SIZE; x += water_cell_size)
{
// Check that the edge at x is partially underwater
float startTerrainHeight[2] = { terrain->GetVertexGroundLevel(x+x1, z+z1), terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) };
float startWaterHeight[2] = { cmpWaterManager->GetExactWaterLevel(x+x1, z+z1), cmpWaterManager->GetExactWaterLevel(x+x1, z+z1 + water_cell_size) };
if (startTerrainHeight[0] >= startWaterHeight[0] && startTerrainHeight[1] >= startWaterHeight[1])
// Check that this tile has at least one vertice underwater.
if (terrain->GetVertexGroundLevel(x+x1, z+z1) >= waterHeight
&& terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) >= waterHeight
&& terrain->GetVertexGroundLevel(x+x1 + water_cell_size, z+z1) >= waterHeight
&& terrain->GetVertexGroundLevel(x+x1 + water_cell_size, z+z1 + water_cell_size) >= waterHeight)
continue;
// This is actually lying and I should call CcmpTerrain
/*if (!terrain->IsOnMap(x+x1, z+z1)
&& !terrain->IsOnMap(x+x1, z+z1 + water_cell_size)
&& !terrain->IsOnMap(x+x1 + water_cell_size, z+z1)
&& !terrain->IsOnMap(x+x1 + water_cell_size, z+z1 + water_cell_size))
continue;*/
// Figure out our points. We might want to draw only one of two triangles per tile.
// In order: the one on the diagonal on top, the one of the diagonal on bottom, other on top, other on bottom.
// The numbers refer to "moves" above. -1 means "not rendering".
// by default the diagonal is the "x,z->x+1,z+1" one.
int points[4] = { 0, 3, 1, 2 };
// If the other diagonal is over water completely, that means we have the wrong diagonal.
if (terrain->GetVertexGroundLevel(x+x1 + water_cell_size, z+z1) >= waterHeight
&& terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) >= waterHeight)
{
points[0] = 1; points[1] = 2; points[2] = 0; points[3] = 3;
}
// check if the diagonal is completely out of the water, and if so, check which triangles we want to render (1 or 2)
if (terrain->GetVertexGroundLevel(x+x1 + moves[points[0]][0], z+z1 + moves[points[0]][1]) >= waterHeight
&& terrain->GetVertexGroundLevel(x+x1 + moves[points[1]][0], z+z1 + moves[points[1]][1]) >= waterHeight)
{
if (terrain->GetVertexGroundLevel(x+x1 + moves[points[2]][0], z+z1 + moves[points[2]][1]) >= waterHeight)
points[2] = -1;
else if (terrain->GetVertexGroundLevel(x+x1 + moves[points[3]][0], z+z1 + moves[points[3]][1]) >= waterHeight)
points[3] = -1;
}
// Compute data.
for (int i = 0; i < 4; ++i)
{
if (points[i] == -1)
continue;
// Check if we already computed this vertex from an earlier strip
if (water_index_map[z+moves[points[i]][1]][x+moves[points[i]][0]] != 0xFFFF)
continue;
ssize_t zz = z+z1+moves[points[i]][1];
ssize_t xx = x+x1+moves[points[i]][0];
SWaterVertex vertex;
terrain->CalcPosition(xx,zz, vertex.m_Position);
float depth = waterHeight - vertex.m_Position.Y;
// Try and get the point on the shore if it's over water.
// In some cases this won't be possible.
if (depth < 0.0f)
{
float temp = 0.0f;
float left_t = 0.0f,right_t = 0.0f,top_t = 0.0f,bottom_t = 0.0f;
if (xx > 0)
{
temp = terrain->GetVertexGroundLevel(xx-1,zz);
if (temp < waterHeight)
left_t = 1.0f-(temp-waterHeight)/(temp-vertex.m_Position.Y);
}
if (xx < mapSize - 1)
{
temp = terrain->GetVertexGroundLevel(xx+1,zz);
if (temp < waterHeight)
right_t = 1.0f-(temp-waterHeight)/(temp-vertex.m_Position.Y);
}
if (zz > 0)
{
temp = terrain->GetVertexGroundLevel(xx,zz-1);
if (temp < waterHeight)
top_t = 1.0f-(temp-waterHeight)/(temp-vertex.m_Position.Y);
}
if (zz < mapSize - 1)
{
temp = terrain->GetVertexGroundLevel(xx,zz-1);
if (temp < waterHeight)
bottom_t = 1.0f-(temp-waterHeight)/(temp-vertex.m_Position.Y);
}
vertex.m_Position.X = vertex.m_Position.X + 4.0 * (right_t - left_t);
vertex.m_Position.Z = vertex.m_Position.Z + 4.0 * (bottom_t - top_t);
}
vertex.m_Position.Y = waterHeight;
m_WaterBounds += vertex.m_Position;
// faking fresnel for simplest water.
float alpha = clamp(depth / WaterMgr->m_WaterFullDepth + WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterAlphaOffset, WaterMgr->m_WaterMaxAlpha);
// Split the depth data across 24 bits, so the fancy-water shader can reconstruct
// the depth value while the simple-water can just use the precomputed alpha
float depthInt = floor(depth);
float depthFrac = depth - depthInt;
vertex.m_DepthData = SColor4ub(u8(clamp(depthInt, 0.0f, 255.0f)),
u8(clamp(-depthInt, 0.0f, 255.0f)),
u8(clamp(depthFrac*255.0f, 0.0f, 255.0f)),
u8(clamp(alpha*255.0f, 0.0f, 255.0f)));
// Move x back one cell (unless at start of patch), then scan rightwards
vertex.m_WaterData = CVector4D(WaterMgr->m_BlurredNormalMap[xx + zz*mapSize].X,
WaterMgr->m_BlurredNormalMap[xx + zz*mapSize].Z,
WaterMgr->m_DistanceHeightmap[xx + zz*mapSize],
0.0f);
water_index_map[z+moves[points[i]][1]][x+moves[points[i]][0]] = water_vertex_data.size();
water_vertex_data.push_back(vertex);
}
// Render them.
if (points[2] == 0) // Top point is wanted, render corresponding triangle
{
water_indices.push_back(water_index_map[z + moves[points[1]][1]][x + moves[points[1]][0]]);
water_indices.push_back(water_index_map[z + moves[points[2]][1]][x + moves[points[2]][0]]);
water_indices.push_back(water_index_map[z + moves[points[0]][1]][x + moves[points[0]][0]]);
}
else if (points[2] == 1)
{
water_indices.push_back(water_index_map[z + moves[points[1]][1]][x + moves[points[1]][0]]);
water_indices.push_back(water_index_map[z + moves[points[0]][1]][x + moves[points[0]][0]]);
water_indices.push_back(water_index_map[z + moves[points[2]][1]][x + moves[points[2]][0]]);
}
if (points[3] == 3) // Bottom point is wanted, render corresponding triangle.
{
water_indices.push_back(water_index_map[z + moves[points[1]][1]][x + moves[points[1]][0]]);
water_indices.push_back(water_index_map[z + moves[points[0]][1]][x + moves[points[0]][0]]);
water_indices.push_back(water_index_map[z + moves[points[3]][1]][x + moves[points[3]][0]]);
}
else if (points[3] == 2)
{
water_indices.push_back(water_index_map[z + moves[points[1]][1]][x + moves[points[1]][0]]);
water_indices.push_back(water_index_map[z + moves[points[3]][1]][x + moves[points[3]][0]]);
water_indices.push_back(water_index_map[z + moves[points[0]][1]][x + moves[points[0]][0]]);
}
/*// Move x back one cell (unless at start of patch), then scan rightwards.
bool belowWater = true;
ssize_t stripStart;
for (stripStart = x = std::max(x-water_cell_size, (ssize_t)0); x <= PATCH_SIZE; x += water_cell_size)
@ -1337,9 +1474,7 @@ void CPatchRData::BuildWater()
// If this edge is not underwater, and neither is the previous edge
// (i.e. belowWater == false), then stop this strip since we've reached
// a cell that's entirely above water
float terrainHeight[2] = { terrain->GetVertexGroundLevel(x+x1, z+z1), terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) };
float waterHeight[2] = { cmpWaterManager->GetExactWaterLevel(x+x1, z+z1), cmpWaterManager->GetExactWaterLevel(x+x1, z+z1 + water_cell_size) };
if (terrainHeight[0] >= waterHeight[0] && terrainHeight[1] >= waterHeight[1])
if (terrain->GetVertexGroundLevel(x+x1, z+z1) >= waterHeight && terrain->GetVertexGroundLevel(x+x1, z+z1 + water_cell_size) >= waterHeight)
{
if (!belowWater)
break;
@ -1404,7 +1539,7 @@ void CPatchRData::BuildWater()
water_indices.push_back(water_index_map[z + water_cell_size][x]);
water_indices.push_back(water_index_map[z][x - water_cell_size]);
water_indices.push_back(water_index_map[z][x]);
}
}*/
}
}
@ -1430,6 +1565,8 @@ void CPatchRData::RenderWater(CShaderProgramPtr& shader)
SWaterVertex *base=(SWaterVertex *)m_VBWater->m_Owner->Bind();
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// setup data pointers
GLsizei stride = sizeof(SWaterVertex);
shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, &base[m_VBWater->m_Index].m_DepthData);
@ -1445,6 +1582,8 @@ void CPatchRData::RenderWater(CShaderProgramPtr& shader)
glDrawElements(GL_TRIANGLES, (GLsizei) m_VBWaterIndices->m_Count,
GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_VBWaterIndices->m_Index));
}
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// bump stats
g_Renderer.m_Stats.m_DrawCalls++;

View file

@ -667,26 +667,23 @@ void CRenderer::SetOptionBool(enum Option opt,bool value)
m_Options.m_Shadows = value;
MakeShadersDirty();
break;
case OPT_WATERNORMAL:
m_Options.m_WaterNormal = value;
case OPT_WATERUGLY:
m_Options.m_WaterUgly = value;
break;
case OPT_WATERFANCYEFFECTS:
m_Options.m_WaterFancyEffects = 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;
case OPT_SHADOWSONWATER:
m_Options.m_WaterShadows = value;
break;
case OPT_SHADOWPCF:
m_Options.m_ShadowPCF = value;
@ -733,20 +730,18 @@ bool CRenderer::GetOptionBool(enum Option opt) const
return m_Options.m_NoVBO;
case OPT_SHADOWS:
return m_Options.m_Shadows;
case OPT_WATERNORMAL:
return m_Options.m_WaterNormal;
case OPT_WATERUGLY:
return m_Options.m_WaterUgly;
case OPT_WATERFANCYEFFECTS:
return m_Options.m_WaterFancyEffects;
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_SHADOWSONWATER:
return m_Options.m_WaterShadows;
case OPT_SHADOWPCF:
return m_Options.m_ShadowPCF;
case OPT_PARTICLES:

View file

@ -80,13 +80,12 @@ public:
enum Option {
OPT_NOVBO,
OPT_SHADOWS,
OPT_WATERNORMAL,
OPT_WATERUGLY,
OPT_WATERFANCYEFFECTS,
OPT_WATERREALDEPTH,
OPT_WATERFOAM,
OPT_WATERCOASTALWAVES,
OPT_WATERREFLECTION,
OPT_WATERREFRACTION,
OPT_WATERSHADOW,
OPT_SHADOWSONWATER,
OPT_SHADOWPCF,
OPT_PARTICLES,
OPT_GENTANGENTS,
@ -143,13 +142,12 @@ public:
bool m_NoVBO;
bool m_Shadows;
bool m_WaterNormal;
bool m_WaterUgly;
bool m_WaterFancyEffects;
bool m_WaterRealDepth;
bool m_WaterFoam;
bool m_WaterCoastalWaves;
bool m_WaterRefraction;
bool m_WaterReflection;
bool m_WaterShadow;
bool m_WaterShadows;
RenderPath m_RenderPath;
bool m_ShadowAlphaFix;

View file

@ -85,7 +85,7 @@ struct TerrainRendererInternals
/// Fancy water shader
CShaderProgramPtr fancyWaterShader;
CShaderProgramPtr wavesShader;
CShaderProgramPtr fancyEffectsShader;
CSimulation2* simulation;
};
@ -632,32 +632,26 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
CShaderDefines defines = context;
WaterMgr->UpdateQuality();
// If we're using fancy water, make sure its shader is loaded
if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading)
{
if (WaterMgr->m_WaterNormal)
defines.Add(str_USE_NORMALS, str_1);
if (WaterMgr->m_WaterRealDepth)
defines.Add(str_USE_REAL_DEPTH, str_1);
if (WaterMgr->m_WaterFoam)
defines.Add(str_USE_FOAM, str_1);
if (WaterMgr->m_WaterCoastalWaves && false)
defines.Add(str_USE_WAVES, str_1);
if (WaterMgr->m_WaterFancyEffects)
defines.Add(str_USE_FANCY_EFFECTS, str_1);
if (WaterMgr->m_WaterRefraction)
defines.Add(str_USE_REFRACTION, str_1);
if (WaterMgr->m_WaterReflection)
defines.Add(str_USE_REFLECTION, str_1);
if (shadow && WaterMgr->m_WaterShadows)
defines.Add(str_USE_SHADOWS, str_1);
defines.Add(str_USE_SHADOWS_ON_WATER, str_1);
m->wavesShader = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", defines);
if (!m->wavesShader)
m->fancyEffectsShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_effects", defines);
if (!m->fancyEffectsShader)
{
LOGERROR(L"Failed to load waves shader. Deactivating waves.\n");
g_Renderer.SetOptionBool(CRenderer::OPT_WATERCOASTALWAVES, false);
defines.Add(str_USE_WAVES, str_0);
LOGERROR(L"Failed to load Fancy effects shader. Deactivating fancy effects.\n");
g_Renderer.SetOptionBool(CRenderer::OPT_WATERFANCYEFFECTS, false);
defines.Add(str_USE_FANCY_EFFECTS, str_0);
}
// haven't updated the ARB shader yet so I'll always load the GLSL
@ -668,7 +662,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
if (!m->fancyWaterShader)
{
LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
LOGERROR(L"Failed to load water shader. Falling back to fixed pipeline water.\n");
WaterMgr->m_RenderWater = false;
return false;
}
@ -717,104 +711,94 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
WaterMgr->CreateSuperfancyInfo();
}*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
double time = WaterMgr->m_WaterTexTimer;
double period = 8;
int curTex = (int)(time*60/period) % 60;
int nexTex = (curTex + 1) % 60;
GLuint FramebufferName = 0;
// rendering waves to a framebuffer
// TODO: reactivate this with something that looks good.
if (false && WaterMgr->m_WaterCoastalWaves && WaterMgr->m_VBWaves && !g_AtlasGameLoop->running)
{
// Save the post-processing framebuffer.
GLint fbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
pglGenFramebuffersEXT(1, &FramebufferName);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferName);
GLuint renderedTexture;
if (WaterMgr->m_waveTT == 0)
{
glGenTextures(1, &renderedTexture);
WaterMgr->m_waveTT = renderedTexture;
glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT);
// TODO: use POT texture
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, WaterMgr->m_waveTT, 0);
glClearColor(0.5f,0.5f,1.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// rendering
m->wavesShader->Bind();
m->wavesShader->BindTexture(str_waveTex, WaterMgr->m_Wave);
m->wavesShader->Uniform(str_time, (float)time);
m->wavesShader->Uniform(str_waviness, WaterMgr->m_Waviness);
m->wavesShader->Uniform(str_mapSize, (float)(WaterMgr->m_MapSize));
SWavesVertex *base=(SWavesVertex *)WaterMgr->m_VBWaves->m_Owner->Bind();
GLsizei stride = sizeof(SWavesVertex);
m->wavesShader->VertexPointer(3, GL_FLOAT, stride, &base[WaterMgr->m_VBWaves->m_Index].m_Position);
m->wavesShader->TexCoordPointer(GL_TEXTURE0,2,GL_BYTE, stride,&base[WaterMgr->m_VBWaves->m_Index].m_UV);
m->wavesShader->AssertPointersBound();
u8* indexBase = WaterMgr->m_VBWavesIndices->m_Owner->Bind();
glDrawElements(GL_TRIANGLES, (GLsizei) WaterMgr->m_VBWavesIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(WaterMgr->m_VBWavesIndices->m_Index));
g_Renderer.m_Stats.m_DrawCalls++;
CVertexBuffer::Unbind();
m->wavesShader->Unbind();
// rebind post-processing frambuffer.
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glBindTexture(GL_TEXTURE_2D, 0);
}
m->fancyWaterShader->Bind();
// 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) );
float repeatPeriod = WaterMgr->m_RepeatPeriod;
GLuint FramebufferName = 0;
// Render normals and foam to a framebuffer if we're in fancy effects
if (WaterMgr->m_WaterFancyEffects)
{
// Save the post-processing framebuffer.
GLint fbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
// Generate our framebuffer
pglGenFramebuffersEXT(1, &FramebufferName);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferName);
GLuint renderedTexture;
if (WaterMgr->m_FancyTexture == 0)
{
glGenTextures(1, &renderedTexture);
WaterMgr->m_FancyTexture = renderedTexture;
glBindTexture(GL_TEXTURE_2D, WaterMgr->m_FancyTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0,GL_RGBA, GL_FLOAT, 0);
} else
glBindTexture(GL_TEXTURE_2D, WaterMgr->m_FancyTexture);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, WaterMgr->m_FancyTexture, 0);
// rendering
m->fancyEffectsShader->Bind();
m->fancyEffectsShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]);
m->fancyEffectsShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]);
m->fancyEffectsShader->Uniform(str_waviness, WaterMgr->m_Waviness);
m->fancyEffectsShader->Uniform(str_translation, tx, ty);
m->fancyEffectsShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
m->fancyEffectsShader->Uniform(str_time, (float)time);
m->fancyEffectsShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
m->fancyEffectsShader->Uniform(str_mapSize, (float)(WaterMgr->m_MapSize));
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
data->RenderWater(m->fancyEffectsShader);
}
m->fancyEffectsShader->Unbind();
// rebind post-processing frambuffer.
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glBindTexture(GL_TEXTURE_2D, 0);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
m->fancyWaterShader->Bind();
const CCamera& camera = g_Renderer.GetViewCamera();
CVector3D camPos = camera.m_Orientation.GetTranslation();
m->fancyWaterShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]);
m->fancyWaterShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]);
if (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves)
{
m->fancyWaterShader->BindTexture(str_Foam, WaterMgr->m_Foam);
m->fancyWaterShader->Uniform(str_mapSize, (float)(WaterMgr->m_MapSize));
}
if (WaterMgr->m_WaterFancyEffects)
m->fancyWaterShader->BindTexture(str_waterEffectsTex, WaterMgr->m_FancyTexture);
if (WaterMgr->m_WaterRealDepth)
m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_depthTT);
if (WaterMgr->m_WaterCoastalWaves)
m->fancyWaterShader->BindTexture(str_waveTex, WaterMgr->m_waveTT);
if (WaterMgr->m_WaterReflection)
m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture);
m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture);
if (WaterMgr->m_WaterRefraction)
m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture);
m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture);
m->fancyWaterShader->BindTexture(str_losMap, losTexture.GetTextureSmooth());
@ -981,6 +965,8 @@ void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup,
{
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
WaterMgr->UpdateQuality();
if (!WaterMgr->WillRenderFancyWater())
RenderSimpleWater(cullGroup);
else

View file

@ -82,10 +82,12 @@ WaterManager::WaterManager()
m_DistanceToShore = NULL;
m_FoamFactor = NULL;
m_WaterNormal = false;
m_DistanceHeightmap = NULL;
m_BlurredNormalMap = NULL;
m_WaterUgly = false;
m_WaterFancyEffects = false;
m_WaterRealDepth = false;
m_WaterFoam = false;
m_WaterCoastalWaves = false;
m_WaterRefraction = false;
m_WaterReflection = false;
m_WaterShadows = false;
@ -97,7 +99,7 @@ WaterManager::WaterManager()
m_VBWavesIndices = NULL;
m_depthTT = 0;
m_waveTT = 0;
m_FancyTexture = 0;
m_MapSize = 0;
@ -117,7 +119,7 @@ WaterManager::~WaterManager()
delete[] m_FoamFactor;
glDeleteTextures(1, &m_depthTT);
glDeleteTextures(1, &m_waveTT);
glDeleteTextures(1, &m_FancyTexture);
if (m_VBWaves) g_VBMan.Release(m_VBWaves);
if (m_VBWavesIndices) g_VBMan.Release(m_VBWavesIndices);
@ -134,14 +136,14 @@ int WaterManager::LoadWaterTextures()
// TODO: add a member variable and setter for this. (can't make this
// a parameter because this function is called via delay-load code)
static const wchar_t* const water_type = L"default";
static const wchar_t* const water_type = L"ocean";
wchar_t pathname[PATH_MAX];
// Load diffuse grayscale images (for non-fancy water)
for (size_t i = 0; i < ARRAY_SIZE(m_WaterTexture); ++i)
{
swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/diffuse%02d.dds", water_type, (int)i+1);
swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/default/diffuse%02d.dds", (int)i+1);
CTextureProperties textureProps(pathname);
textureProps.SetWrap(GL_REPEAT);
@ -153,7 +155,7 @@ int WaterManager::LoadWaterTextures()
// Load normalmaps (for fancy water)
for (size_t i = 0; i < ARRAY_SIZE(m_NormalMap); ++i)
{
swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/normal%02d.dds", water_type, (int)i+1);
swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/normal00%02d.png", water_type, (int)i+1);
CTextureProperties textureProps(pathname);
textureProps.SetWrap(GL_REPEAT);
textureProps.SetMaxAnisotropy(4);
@ -162,6 +164,7 @@ int WaterManager::LoadWaterTextures()
texture->Prefetch();
m_NormalMap[i] = texture;
}
// Load foam (for fancy water)
{
CTextureProperties textureProps("art/textures/terrain/types/water/foam.png");
@ -234,6 +237,128 @@ void WaterManager::UnloadWaterTextures()
}
}
///////////////////////////////////////////////////////////////////
// Calculate our binary heightmap from the terrain heightmap.
void WaterManager::RecomputeDistanceHeightmap()
{
if (m_DistanceHeightmap == NULL)
m_DistanceHeightmap = new u8[m_MapSize*m_MapSize];
// Custom copy the heightmap.
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
u16 waterLevel = m_WaterHeight/HEIGHT_SCALE;
u16* heightmap = terrain->GetHeightMap();
// We will "expand" the heightmap. That is we'll set each vertex on land as "3", and "bleed" that onto neighboring pixels.
// So 3 is "on land", 2 is "close", 1 "somewhat close" and 0 is "water".
// This gives a basic manhattan approximation of how close to the coast we are.
// I have a heathen fondness for ternary operators so there are some below.
u8 level = 0;
for (size_t z = 0; z < m_MapSize; ++z)
{
level = 0;
for (size_t x = 0; x < m_MapSize; ++x)
m_DistanceHeightmap[z*m_MapSize + x] = heightmap[z*m_MapSize + x] >= waterLevel ? level = 3
: level > 0 ? --level : 0;
level = 0;
for (size_t x = m_MapSize-1; x != (size_t)-1; --x)
{
if (heightmap[z*m_MapSize + x] >= waterLevel)
level = 3; // no need to set m_distanceHeightmap, it's already been done by the other loop.
else
{
level > 0 ? --level : 0;
if (level > m_DistanceHeightmap[z*m_MapSize + x])
m_DistanceHeightmap[z*m_MapSize + x] = level;
}
}
}
for (size_t x = 0; x < m_MapSize; ++x)
{
level = 0;
for (size_t z = 0; z < m_MapSize; ++z)
{
if (heightmap[z*m_MapSize + x] >= waterLevel)
level = 3;
else
{
level > 0 ? --level : 0;
if (level > m_DistanceHeightmap[z*m_MapSize + x])
m_DistanceHeightmap[z*m_MapSize + x] = level;
}
}
level = 0;
for (size_t z = m_MapSize-1; z != (size_t)-1; --z)
{
if (heightmap[z*m_MapSize + x] >= waterLevel)
level = 3;
else
{
level > 0 ? --level : 0;
if (level > m_DistanceHeightmap[z*m_MapSize + x])
m_DistanceHeightmap[z*m_MapSize + x] = level;
}
}
}
}
///////////////////////////////////////////////////////////////////
// Calculate The blurred normal map to get an idea of where water ought to go.
void WaterManager::RecomputeBlurredNormalMap()
{
// used to cache terrain normals since otherwise we'd recalculate them a lot (I'm blurring the "normal" map).
// this might be updated to actually cache in the terrain manager but that's not for now.
if (m_BlurredNormalMap == NULL)
m_BlurredNormalMap = new CVector3D[m_MapSize*m_MapSize];
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
// It's really slow to calculate normals so cache them first.
CVector3D* normals = new CVector3D[m_MapSize*m_MapSize];
// Not the edges, we won't care about them.
float ii = 8.0f, jj = 8.0f;
for (size_t j = 2; j < m_MapSize-2; ++j, jj += 4.0f)
for (size_t i = 2; i < m_MapSize-2; ++i, ii += 4.0f)
{
CVector3D norm;
terrain->CalcNormal(i,j,norm);
normals[j*m_MapSize + i] = norm;
}
// We could be way fancier (and faster) for our blur but we probably don't need the complexity.
// Two pass filter, nothing complicated here.
CVector3D blurValue;
ii = 8.0f; jj = 8.0f;
size_t idx = 2;
for (size_t j = 2; j < m_MapSize-2; ++j, jj += 4.0f)
for (size_t i = 2; i < m_MapSize-2; ++i, ii += 4.0f,++idx)
{
blurValue = normals[idx-2];
blurValue += normals[idx-1];
blurValue += normals[idx];
blurValue += normals[idx+1];
blurValue += normals[idx+2];
m_BlurredNormalMap[idx] = blurValue * 0.2f;
}
// y direction, probably slower because of cache misses but I don't see an easy way around that.
ii = 8.0f; jj = 8.0f;
for (size_t i = 2; i < m_MapSize-2; ++i, ii += 4.0f)
{
for (size_t j = 2; j < m_MapSize-2; ++j, jj += 4.0f)
{
blurValue = normals[(j-2)*m_MapSize + i];
blurValue += normals[(j-1)*m_MapSize + i];
blurValue += normals[j*m_MapSize + i];
blurValue += normals[(j+1)*m_MapSize + i];
blurValue += normals[(j+2)*m_MapSize + i];
m_BlurredNormalMap[j*m_MapSize + i] = blurValue * 0.2f;
}
}
}
///////////////////////////////////////////////////////////////////
// Create information about the terrain and wave vertices.
void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
@ -248,7 +373,7 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
g_VBMan.Release(m_VBWavesIndices);
m_VBWavesIndices = NULL;
}
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
CmpPtr<ICmpWaterManager> cmpWaterManager(*simulation, SYSTEM_ENTITY);
@ -608,7 +733,7 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
}
////////////////////////////////////////////////////////////////////////
// This will always recalculate for now
// TODO: This will always recalculate for now
void WaterManager::SetMapSize(size_t size)
{
// TODO: Im' blindly trusting the user here.
@ -619,6 +744,8 @@ void WaterManager::SetMapSize(size_t size)
m_updatej0 = 0;
m_updatej1 = size;
SAFE_ARRAY_DELETE(m_DistanceHeightmap);
SAFE_ARRAY_DELETE(m_BlurredNormalMap);
SAFE_ARRAY_DELETE(m_WaveX);
SAFE_ARRAY_DELETE(m_WaveZ);
SAFE_ARRAY_DELETE(m_DistanceToShore);
@ -629,24 +756,18 @@ void WaterManager::SetMapSize(size_t size)
// 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);
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERUGLY) != m_WaterUgly) {
m_WaterUgly = g_Renderer.GetOptionBool(CRenderer::OPT_WATERUGLY);
m_NeedsReloading = true;
}
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERFANCYEFFECTS) != m_WaterFancyEffects) {
m_WaterFancyEffects = g_Renderer.GetOptionBool(CRenderer::OPT_WATERFANCYEFFECTS);
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_NeedInfoUpdate = true;
}
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES) != m_WaterCoastalWaves) {
m_WaterCoastalWaves = g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES);
m_NeedsReloading = true;
m_NeedInfoUpdate = true;
}
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION) != m_WaterRefraction) {
m_WaterRefraction = g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION);
m_NeedsReloading = true;
@ -655,8 +776,8 @@ void WaterManager::UpdateQuality()
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);
if (g_Renderer.GetOptionBool(CRenderer::OPT_SHADOWSONWATER) != m_WaterShadows) {
m_WaterShadows = g_Renderer.GetOptionBool(CRenderer::OPT_SHADOWSONWATER);
m_NeedsReloading = true;
}
}
@ -665,7 +786,7 @@ bool WaterManager::WillRenderFancyWater()
{
if (!g_Renderer.GetCapabilities().m_FragmentShader)
return false;
if (!m_RenderWater)
if (!m_RenderWater || m_WaterUgly)
return false;
return true;
}

View file

@ -58,11 +58,14 @@ public:
float* m_DistanceToShore;
float* m_FoamFactor;
u8* m_DistanceHeightmap; // Returns how far from the shore a point is. 3-2-1-0 where 3 is "on land"
CVector3D* m_BlurredNormalMap; // Returns how far from the shore a point is. 3-2-1-0 where 3 is "on land"
size_t m_MapSize;
ssize_t m_TexSize;
GLuint m_depthTT;
GLuint m_waveTT;
GLuint m_FancyTexture;
// used to know what to update when updating parts of the terrain only.
u32 m_updatei0;
@ -74,13 +77,18 @@ public:
CColor m_WaterColor;
bool m_RenderWater;
// Force the use of the fixed function for rendering.
bool m_WaterUgly;
// Those variables register the current quality level. If there is a change, I have to recompile the shader.
bool m_WaterNormal;
// Use real depth or use the fake precomputed one.
bool m_WaterRealDepth;
bool m_WaterFoam;
bool m_WaterCoastalWaves;
// Use fancy shore effects and show trails behind ships
bool m_WaterFancyEffects;
// Use refractions instead of simply making the water more or less transparent.
bool m_WaterRefraction;
// Use complete reflections instead of showing merely the sky.
bool m_WaterReflection;
// Show shadows on the water.
bool m_WaterShadows;
bool m_NeedsReloading;
@ -145,6 +153,17 @@ public:
*/
void UnloadWaterTextures();
/**
* RecomputeDistanceHeightmap: recalculates (or calculates) the distance heightmap.
*/
void RecomputeDistanceHeightmap();
/**
* RecomputeBlurredNormalMap: calculates the blurred normal map of the terrain. Slow.
*/
void RecomputeBlurredNormalMap();
/**
* CreateSuperfancyInfo: creates textures and wave vertices for superfancy water
*/

View file

@ -34,15 +34,14 @@ void JSI_Renderer::Set##SCRIPTNAME##Enabled(ScriptInterface::CxPrivate* UNUSED(p
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PARTICLES, Particles);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(GENTANGENTS, GenTangents);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PREFERGLSL, PreferGLSL);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERNORMAL, WaterNormal);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERUGLY, WaterUgly);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERFANCYEFFECTS, WaterFancyEffects);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SHADOWPCF, ShadowPCF);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SHADOWS, Shadows);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERREALDEPTH, WaterRealDepth);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERREFLECTION, WaterReflection);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERREFRACTION, WaterRefraction);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERFOAM, WaterFoam);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERCOASTALWAVES, WaterCoastalWaves);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WATERSHADOW, WaterShadow);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SHADOWSONWATER, WaterShadows);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SILHOUETTES, Silhouettes);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SHOWSKY, ShowSky);
IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SMOOTHLOS, SmoothLOS);
@ -75,13 +74,12 @@ void JSI_Renderer::RegisterScriptFunctions(ScriptInterface& scriptInterface)
REGISTER_BOOLEAN_SCRIPT_SETTING(Particles);
REGISTER_BOOLEAN_SCRIPT_SETTING(GenTangents);
REGISTER_BOOLEAN_SCRIPT_SETTING(PreferGLSL);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterNormal);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterUgly);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRealDepth);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterReflection);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRefraction);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterFoam);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterCoastalWaves);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterShadow);
REGISTER_BOOLEAN_SCRIPT_SETTING(WaterShadows);
REGISTER_BOOLEAN_SCRIPT_SETTING(Silhouettes);
REGISTER_BOOLEAN_SCRIPT_SETTING(ShowSky);
REGISTER_BOOLEAN_SCRIPT_SETTING(SmoothLOS);

View file

@ -35,13 +35,12 @@ namespace JSI_Renderer
DECLARE_BOOLEAN_SCRIPT_SETTING(Particles);
DECLARE_BOOLEAN_SCRIPT_SETTING(GenTangents);
DECLARE_BOOLEAN_SCRIPT_SETTING(PreferGLSL);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterNormal);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterUgly);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRealDepth);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterReflection);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRefraction);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterFoam);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterCoastalWaves);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterShadow);
DECLARE_BOOLEAN_SCRIPT_SETTING(WaterShadows);
DECLARE_BOOLEAN_SCRIPT_SETTING(Silhouettes);
DECLARE_BOOLEAN_SCRIPT_SETTING(ShowSky);
DECLARE_BOOLEAN_SCRIPT_SETTING(SmoothLOS);

View file

@ -136,8 +136,11 @@ public:
}
if (ReloadWater && CRenderer::IsInitialised())
{
g_Renderer.GetWaterManager()->SetMapSize(vertices);
g_Renderer.GetWaterManager()->RecomputeDistanceHeightmap();
g_Renderer.GetWaterManager()->RecomputeBlurredNormalMap();
}
MakeDirty(0, 0, tiles+1, tiles+1);
}

View file

@ -33,6 +33,7 @@ class CCmpWaterManager : public ICmpWaterManager
public:
static void ClassInit(CComponentManager& componentManager)
{
// No need to subscribe to WaterChanged since we're actually the one sending those.
componentManager.SubscribeToMessageType(MT_Interpolate);
componentManager.SubscribeToMessageType(MT_TerrainChanged);
}
@ -50,7 +51,6 @@ public:
virtual void Init(const CParamNode& UNUSED(paramNode))
{
SetWaterLevel(entity_pos_t::FromInt(5));
}
virtual void Deinit()
@ -119,6 +119,8 @@ public:
// Tell the terrain it'll need to recompute its cached render data
GetSimContext().GetTerrain().MakeDirty(RENDERDATA_UPDATE_VERTICES);
g_Renderer.GetWaterManager()->m_WaterHeight = h.ToFloat();
CMessageWaterChanged msg;
GetSimContext().GetComponentManager().BroadcastMessage(msg);
}