Index: ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_fragment.h
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_fragment.h (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_fragment.h (revision 24732)
@@ -0,0 +1,21 @@
+#ifndef INCLUDED_LOS_FRAGMENT
+#define INCLUDED_LOS_FRAGMENT
+
+#if !IGNORE_LOS
+ uniform sampler2D losTex;
+
+ varying vec2 v_los;
+#endif
+
+float getLOS()
+{
+#if !IGNORE_LOS
+ float los = texture2D(losTex, v_los).a;
+ float threshold = 0.03;
+ return (los - threshold) / (1.0 - threshold);
+#else
+ return 1.0;
+#endif
+}
+
+#endif // INCLUDED_LOS_FRAGMENT
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_fragment.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_vertex.h
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_vertex.h (nonexistent)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_vertex.h (revision 24732)
@@ -0,0 +1,17 @@
+#ifndef INCLUDED_LOS_VERTEX
+#define INCLUDED_LOS_VERTEX
+
+#if !IGNORE_LOS
+ uniform vec2 losTransform;
+
+ varying vec2 v_los;
+#endif
+
+void calculateLOSCoordinates(vec2 position)
+{
+#if !IGNORE_LOS
+ v_los = position * losTransform.x + losTransform.y;
+#endif
+}
+
+#endif // INCLUDED_LOS_VERTEX
Property changes on: ps/trunk/binaries/data/mods/public/shaders/glsl/common/los_vertex.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.fs (revision 24732)
@@ -1,183 +1,178 @@
#version 120
#include "common/fog.h"
+#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
-uniform sampler2D losTex;
uniform sampler2D aoTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
#if USE_OBJECTCOLOR
uniform vec3 objectColor;
#else
#if USE_PLAYERCOLOR
uniform vec3 playerColor;
#endif
#endif
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
varying vec4 v_lighting;
varying vec2 v_tex;
-varying vec2 v_los;
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
varying vec2 v_tex2;
#endif
#if USE_SPECULAR
uniform float specularPower;
uniform vec3 specularColor;
#endif
#if USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX || USE_AO
uniform vec4 effectSettings;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX
varying vec4 v_normal;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX)
varying vec4 v_tangent;
//varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
varying vec3 v_eyeVec;
#endif
#endif
void main()
{
vec2 coord = v_tex;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_PARALLAX || USE_NORMAL_MAP)
vec3 bitangent = vec3(v_normal.w, v_tangent.w, v_lighting.w);
mat3 tbn = mat3(v_tangent.xyz, bitangent, v_normal.xyz);
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
{
float h = texture2D(normTex, coord).a;
vec3 eyeDir = normalize(v_eyeVec * tbn);
float dist = length(v_eyeVec);
vec2 move;
float height = 1.0;
float scale = effectSettings.z;
int iter = int(min(20.0, 25.0 - dist/10.0));
if (iter > 0)
{
float s = 1.0/float(iter);
float t = s;
move = vec2(-eyeDir.x, eyeDir.y) * scale / (eyeDir.z * float(iter));
vec2 nil = vec2(0.0);
for (int i = 0; i < iter; ++i) {
height -= t;
t = (h < height) ? s : 0.0;
vec2 temp = (h < height) ? move : nil;
coord += temp;
h = texture2D(normTex, coord).a;
}
// Move back to where we collided with the surface.
// This assumes the surface is linear between the sample point before we
// intersect the surface and after we intersect the surface
float hp = texture2D(normTex, coord - move).a;
coord -= move * ((h - height) / (s + h - hp));
}
}
#endif
vec4 tex = texture2D(baseTex, coord);
// Alpha-test as early as possible
#ifdef REQUIRE_ALPHA_GEQUAL
if (tex.a < REQUIRE_ALPHA_GEQUAL)
discard;
#endif
#if USE_TRANSPARENT
gl_FragColor.a = tex.a;
#else
gl_FragColor.a = 1.0;
#endif
vec3 texdiffuse = tex.rgb;
// Apply-coloring based on texture alpha
#if USE_OBJECTCOLOR
texdiffuse *= mix(objectColor, vec3(1.0, 1.0, 1.0), tex.a);
#else
#if USE_PLAYERCOLOR
texdiffuse *= mix(playerColor, vec3(1.0, 1.0, 1.0), tex.a);
#endif
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP
vec3 normal = v_normal.xyz;
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_NORMAL_MAP
vec3 ntex = texture2D(normTex, coord).rgb * 2.0 - 1.0;
ntex.y = -ntex.y;
normal = normalize(tbn * ntex);
vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
#else
vec3 sundiffuse = v_lighting.rgb;
#endif
vec4 specular = vec4(0.0);
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 specCol;
float specPow;
#if USE_SPECULAR_MAP
vec4 s = texture2D(specTex, coord);
specCol = s.rgb;
specular.a = s.a;
specPow = effectSettings.y;
#else
specCol = specularColor;
specPow = specularPower;
#endif
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;
#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);
ambColor *= ao;
#endif
color += ambColor;
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);
#endif
color = applyFog(color);
- #if !IGNORE_LOS
- float los = texture2D(losTex, v_los).a;
- los = los < 0.03 ? 0.0 : los;
- color *= los;
- #endif
+ color *= getLOS();
color *= shadingColor;
gl_FragColor.rgb = color;
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_common.vs (revision 24732)
@@ -1,172 +1,171 @@
#version 120
+#include "common/los_vertex.h"
#include "common/shadows_vertex.h"
uniform mat4 transform;
uniform vec3 cameraPos;
#ifdef GL_ES
uniform mediump vec3 sunDir;
uniform mediump vec3 sunColor;
#else
uniform vec3 sunDir;
uniform vec3 sunColor;
#endif
-uniform vec2 losTransform;
uniform mat4 instancingTransform;
#if USE_WIND
uniform vec4 sim_time;
uniform vec4 windData;
#endif
varying vec4 v_lighting;
varying vec2 v_tex;
-varying vec2 v_los;
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
varying vec2 v_tex2;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX
varying vec4 v_normal;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX)
varying vec4 v_tangent;
//varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
varying vec3 v_eyeVec;
#endif
#endif
attribute vec3 a_vertex;
attribute vec3 a_normal;
#if (USE_INSTANCING || USE_GPU_SKINNING)
attribute vec4 a_tangent;
#endif
attribute vec2 a_uv0;
attribute vec2 a_uv1;
#if USE_GPU_SKINNING
const int MAX_INFLUENCES = 4;
const int MAX_BONES = 64;
uniform mat4 skinBlendMatrices[MAX_BONES];
attribute vec4 a_skinJoints;
attribute vec4 a_skinWeights;
#endif
vec4 fakeCos(vec4 x)
{
vec4 tri = abs(fract(x + 0.5) * 2.0 - 1.0);
- return tri * tri *(3.0 - 2.0 * tri);
+ return tri * tri *(3.0 - 2.0 * tri);
}
void main()
{
#if USE_GPU_SKINNING
vec3 p = vec3(0.0);
vec3 n = vec3(0.0);
for (int i = 0; i < MAX_INFLUENCES; ++i) {
int joint = int(a_skinJoints[i]);
if (joint != 0xff) {
mat4 m = skinBlendMatrices[joint];
p += vec3(m * vec4(a_vertex, 1.0)) * a_skinWeights[i];
n += vec3(m * vec4(a_normal, 0.0)) * a_skinWeights[i];
}
}
vec4 position = instancingTransform * vec4(p, 1.0);
mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz);
vec3 normal = normalMatrix * normalize(n);
#if (USE_NORMAL_MAP || USE_PARALLAX)
vec3 tangent = normalMatrix * a_tangent.xyz;
#endif
#else
#if (USE_INSTANCING)
vec4 position = instancingTransform * vec4(a_vertex, 1.0);
mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz);
vec3 normal = normalMatrix * a_normal;
#if (USE_NORMAL_MAP || USE_PARALLAX)
vec3 tangent = normalMatrix * a_tangent.xyz;
#endif
#else
vec4 position = vec4(a_vertex, 1.0);
vec3 normal = a_normal;
#endif
#endif
#if USE_WIND
vec2 wind = windData.xy;
// fractional part of model position, clamped to >.4
vec4 modelPos = instancingTransform[3];
modelPos = fract(modelPos);
modelPos = clamp(modelPos, 0.4, 1.0);
// crude measure of wind intensity
float abswind = abs(wind.x) + abs(wind.y);
vec4 cosVec;
// these determine the speed of the wind's "cosine" waves.
cosVec.w = 0.0;
cosVec.x = sim_time.x * modelPos[0] + position.x;
cosVec.y = sim_time.x * modelPos[2] / 3.0 + instancingTransform[3][0];
cosVec.z = sim_time.x * abswind / 4.0 + position.z;
// calculate "cosines" in parallel, using a smoothed triangle wave
cosVec = fakeCos(cosVec);
float limit = clamp((a_vertex.x * a_vertex.z * a_vertex.y) / 3000.0, 0.0, 0.2);
- float diff = cosVec.x * limit;
+ float diff = cosVec.x * limit;
float diff2 = cosVec.y * clamp(a_vertex.y / 60.0, 0.0, 0.25);
// fluttering of model parts based on distance from model center (ie longer branches)
position.xyz += cosVec.z * limit * clamp(abswind, 1.2, 1.7);
// swaying of trunk based on distance from ground (higher parts sway more)
position.xz += diff + diff2 * wind;
#endif
gl_Position = transform * position;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_PARALLAX
v_normal.xyz = normal;
#if (USE_INSTANCING || USE_GPU_SKINNING) && (USE_NORMAL_MAP || USE_PARALLAX)
v_tangent.xyz = tangent;
vec3 bitangent = cross(v_normal.xyz, v_tangent.xyz) * a_tangent.w;
v_normal.w = bitangent.x;
v_tangent.w = bitangent.y;
v_lighting.w = bitangent.z;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_PARALLAX
vec3 eyeVec = cameraPos.xyz - position.xyz;
- #if USE_SPECULAR || USE_SPECULAR_MAP
+ #if USE_SPECULAR || USE_SPECULAR_MAP
vec3 sunVec = -sunDir;
v_half = normalize(sunVec + normalize(eyeVec));
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_PARALLAX
v_eyeVec = eyeVec;
#endif
#endif
#endif
-
+
v_lighting.xyz = max(0.0, dot(normal, -sunDir)) * sunColor;
v_tex = a_uv0;
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_AO
v_tex2 = a_uv1;
#endif
calculatePositionInShadowSpace(position);
- v_los = position.xz * losTransform.x + losTransform.y;
+ calculateLOSCoordinates(position.xz);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.fs (revision 24732)
@@ -1,108 +1,100 @@
#version 120
+#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
-uniform sampler2D losTex;
uniform sampler2D aoTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
uniform sampler2D waterTex;
uniform samplerCube skyCube;
#if USE_OBJECTCOLOR
uniform vec3 objectColor;
#else
#if USE_PLAYERCOLOR
uniform vec3 playerColor;
#endif
#endif
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec3 cameraPos;
uniform float specularStrength;
uniform float waviness;
uniform vec3 waterTint;
uniform float murkiness;
uniform vec3 reflectionTint;
uniform float reflectionTintStrength;
-float waterDepth = 4.0;
+float waterDepth = 4.0;
float fullDepth = 5.0; // Depth at which to use full murkiness (shallower water will be clearer)
varying vec4 worldPos;
varying vec4 v_tex;
-varying vec2 v_los;
void main()
{
vec3 n, l, h, v; // Normal, light vector, half-vector and view vector (vector to eye)
float ndotl, ndoth, ndotv;
float fresnel;
float t; // Temporary variable
vec2 reflCoords, refrCoords;
vec3 reflColor, refrColor, specular;
- float losMod;
//vec4 wtex = textureGrad(waterTex, vec3(fract(v_tex.xy), v_tex.z), dFdx(v_tex.xy), dFdy(v_tex.xy));
vec4 wtex = texture2D(waterTex, fract(v_tex.xy));
n = normalize(wtex.xzy - vec3(0.5, 0.5, 0.5));
l = -sunDir;
v = normalize(cameraPos - worldPos.xyz);
h = normalize(l + v);
-
+
ndotl = dot(n, l);
ndoth = dot(n, h);
ndotv = dot(n, v);
-
+
fresnel = pow(1.0 - ndotv, 0.8); // A rather random Fresnel approximation
-
+
//refrCoords = (0.5*gl_TexCoord[2].xy - 0.8*waviness*n.xz) / gl_TexCoord[2].w + 0.5; // Unbias texture coords
//reflCoords = (0.5*gl_TexCoord[1].xy + waviness*n.xz) / gl_TexCoord[1].w + 0.5; // Unbias texture coords
-
+
//vec3 dir = normalize(v + vec3(waviness*n.x, 0.0, waviness*n.z));
vec3 eye = reflect(v, n);
-
+
vec3 tex = textureCube(skyCube, eye).rgb;
- reflColor = mix(tex, sunColor * reflectionTint,
+ reflColor = mix(tex, sunColor * reflectionTint,
reflectionTintStrength);
//waterDepth = 4.0 + 2.0 * dot(abs(v_tex.zw - 0.5), vec2(0.5));
waterDepth = 4.0;
-
+
//refrColor = (0.5 + 0.5*ndotl) * mix(texture2D(refractionMap, refrCoords).rgb, sunColor * tint,
refrColor = (0.5 + 0.5*ndotl) * mix(vec3(0.3), sunColor * waterTint,
murkiness * clamp(waterDepth / fullDepth, 0.0, 1.0)); // Murkiness and tint at this pixel (tweaked based on lighting and depth)
-
- specular = pow(max(0.0, ndoth), 150.0f) * sunColor * specularStrength;
- losMod = texture2D(losTex, v_los).a;
+ specular = pow(max(0.0, ndoth), 150.0f) * sunColor * specularStrength;
#if USE_SHADOW
float shadow = get_shadow();
float fresShadow = mix(fresnel, fresnel*shadow, dot(sunColor, vec3(0.16666)));
#else
float fresShadow = fresnel;
#endif
-
- vec3 color = mix(refrColor + 0.3*specular, reflColor + specular, fresShadow);
- gl_FragColor.rgb = color * losMod;
+ vec3 color = mix(refrColor + 0.3*specular, reflColor + specular, fresShadow);
+ gl_FragColor.rgb = color * getLOS();
- //gl_FragColor.rgb = mix(refrColor + 0.3*specular, reflColor + specular, fresnel) * losMod;
-
// 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.7 - v.y);
gl_FragColor.a = 0.15 * waterDepth * (1.2 + t + fresnel);
}
-
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_water.vs (revision 24732)
@@ -1,59 +1,58 @@
#if USE_GPU_SKINNING
// Skinning requires GLSL 1.30 for ivec4 vertex attributes
#version 130
#else
#version 120
#endif
+#include "common/los_vertex.h"
#include "common/shadows_vertex.h"
uniform mat4 transform;
uniform vec3 cameraPos;
uniform vec3 sunDir;
uniform vec3 sunColor;
-uniform vec2 losTransform;
uniform mat4 instancingTransform;
uniform float sim_time;
uniform vec2 translation;
attribute vec3 a_vertex;
attribute vec3 a_normal;
#if USE_INSTANCING
attribute vec4 a_tangent;
#endif
attribute vec2 a_uv0;
attribute vec2 a_uv1;
#if USE_GPU_SKINNING
const int MAX_INFLUENCES = 4;
const int MAX_BONES = 64;
uniform mat4 skinBlendMatrices[MAX_BONES];
attribute ivec4 a_skinJoints;
attribute vec4 a_skinWeights;
#endif
varying vec4 worldPos;
varying vec4 v_tex;
-varying vec2 v_los;
vec4 fakeCos(vec4 x)
{
vec4 tri = abs(fract(x + 0.5) * 2.0 - 1.0);
- return tri * tri *(3.0 - 2.0 * tri);
+ return tri * tri *(3.0 - 2.0 * tri);
}
void main()
{
worldPos = instancingTransform * vec4(a_vertex, 1.0);
-
+
v_tex.xy = (a_uv0 + worldPos.xz) / 5.0 + sim_time * translation;
v_tex.zw = a_uv0;
calculatePositionInShadowSpace(worldPos);
- v_los = worldPos.xz * losTransform.x + losTransform.y;
+ calculateLOSCoordinates(worldPos.xz);
gl_Position = transform * worldPos;
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.fs (revision 24732)
@@ -1,47 +1,42 @@
#version 120
+#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
-uniform sampler2D losTex;
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec3 cameraPos;
uniform float specularPower;
uniform vec3 specularColor;
varying vec4 v_tex;
-varying vec2 v_los;
varying vec3 v_half;
varying vec3 v_normal;
varying float v_transp;
varying vec3 v_lighting;
void main()
{
//vec4 texdiffuse = textureGrad(baseTex, vec3(fract(v_tex.xy), v_tex.z), dFdx(v_tex.xy), dFdy(v_tex.xy));
vec4 texdiffuse = texture2D(baseTex, fract(v_tex.xy));
if (texdiffuse.a < 0.25)
discard;
texdiffuse.a *= v_transp;
vec3 specular = sunColor * specularColor * pow(max(0.0, dot(normalize(v_normal), v_half)), specularPower);
vec3 color = (texdiffuse.rgb * v_lighting + specular) * get_shadow();
color += texdiffuse.rgb * ambient;
- #if !IGNORE_LOS
- float los = texture2D(losTex, v_los).a;
- los = los < 0.03 ? 0.0 : los;
- color *= los;
- #endif
+ color *= getLOS();
gl_FragColor.rgb = color;
gl_FragColor.a = texdiffuse.a;
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/model_waterfall.vs (revision 24732)
@@ -1,54 +1,52 @@
#if USE_GPU_SKINNING
// Skinning requires GLSL 1.30 for ivec4 vertex attributes
#version 130
#else
#version 120
#endif
+#include "common/los_vertex.h"
#include "common/shadows_vertex.h"
uniform mat4 transform;
uniform vec3 cameraPos;
uniform vec3 sunDir;
uniform vec3 sunColor;
-uniform vec2 losTransform;
uniform mat4 instancingTransform;
uniform float sim_time;
uniform vec2 translation;
attribute vec3 a_vertex;
attribute vec3 a_normal;
attribute vec2 a_uv0;
attribute vec2 a_uv1;
varying vec4 worldPos;
varying vec4 v_tex;
-varying vec2 v_los;
varying vec3 v_half;
varying vec3 v_normal;
varying float v_transp;
varying vec3 v_lighting;
void main()
{
worldPos = instancingTransform * vec4(a_vertex, 1.0);
-
+
v_tex.xy = a_uv0 + sim_time * translation;
v_transp = a_uv1.x;
calculatePositionInShadowSpace(worldPos);
- v_los = worldPos.xz * losTransform.x + losTransform.y;
+ calculateLOSCoordinates(worldPos.xz);
vec3 eyeVec = cameraPos.xyz - worldPos.xyz;
- vec3 sunVec = -sunDir;
- v_half = normalize(sunVec + normalize(eyeVec));
+ vec3 sunVec = -sunDir;
+ v_half = normalize(sunVec + normalize(eyeVec));
mat3 normalMatrix = mat3(instancingTransform[0].xyz, instancingTransform[1].xyz, instancingTransform[2].xyz);
v_normal = normalMatrix * a_normal;
v_lighting = max(0.0, dot(v_normal, -sunDir)) * sunColor;
gl_Position = transform * worldPos;
}
-
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.fs (revision 24732)
@@ -1,40 +1,33 @@
#version 120
+#include "common/los_fragment.h"
+
uniform sampler2D baseTex;
uniform sampler2D maskTex;
-uniform sampler2D losTex;
#if USE_OBJECTCOLOR
uniform vec4 objectColor;
#else
varying vec4 v_color;
#endif
varying vec2 v_tex;
-#if !IGNORE_LOS
-varying vec2 v_los;
-#endif
-
void main()
{
#if USE_OBJECTCOLOR
vec3 color = objectColor.rgb;
float alpha = objectColor.a;
#else
vec3 color = v_color.rgb;
float alpha = v_color.a;
#endif
vec4 base = texture2D(baseTex, v_tex);
vec4 mask = texture2D(maskTex, v_tex);
color = mix(base.rgb, color, mask.r);
-#if !IGNORE_LOS
- float los = texture2D(losTex, v_los).a;
- los = los < 0.03 ? 0.0 : los;
- color *= los;
-#endif
+ color *= getLOS();
gl_FragColor = vec4(color, alpha * base.a);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/overlayline.vs (revision 24732)
@@ -1,31 +1,23 @@
#version 120
-#if !IGNORE_LOS
-uniform vec2 losTransform;
-#endif
+#include "common/los_vertex.h"
attribute vec3 a_vertex;
attribute vec2 a_uv0;
#if !USE_OBJECTCOLOR
attribute vec4 a_color;
varying vec4 v_color;
#endif
varying vec2 v_tex;
-#if !IGNORE_LOS
-varying vec2 v_los;
-#endif
-
void main()
{
v_tex = a_uv0;
-#if !IGNORE_LOS
- v_los = a_vertex.xz * losTransform.x + losTransform.yy;
-#endif
+ calculateLOSCoordinates(a_vertex.xz);
#if !USE_OBJECTCOLOR
v_color = a_color;
#endif
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_vertex, 1.0);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/particle.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/particle.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/particle.fs (revision 24732)
@@ -1,25 +1,21 @@
#version 110
#include "common/fog.h"
+#include "common/los_fragment.h"
uniform sampler2D baseTex;
-uniform sampler2D losTex;
varying vec2 v_tex;
-varying vec2 v_los;
varying vec4 v_color;
uniform vec3 sunColor;
void main()
{
vec4 color = texture2D(baseTex, v_tex) * vec4((v_color.rgb + sunColor)/2.0,v_color.a);
-
- float los = texture2D(losTex, v_los).a;
- los = los < 0.03 ? 0.0 : los;
- color.rgb *= los;
color.rgb = applyFog(color.rgb);
+ color.rgb *= getLOS();
gl_FragColor = color;
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/particle.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/particle.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/particle.vs (revision 24732)
@@ -1,29 +1,30 @@
#version 110
+#include "common/los_vertex.h"
+
uniform mat4 transform;
uniform mat4 modelViewMatrix;
-uniform vec2 losTransform;
varying vec2 v_tex;
-varying vec2 v_los;
varying vec4 v_color;
attribute vec3 a_vertex;
attribute vec4 a_color;
attribute vec2 a_uv0;
attribute vec2 a_uv1;
void main()
{
vec3 axis1 = vec3(modelViewMatrix[0][0], modelViewMatrix[1][0], modelViewMatrix[2][0]);
vec3 axis2 = vec3(modelViewMatrix[0][1], modelViewMatrix[1][1], modelViewMatrix[2][1]);
vec2 offset = a_uv1;
vec3 position = axis1*offset.x + axis1*offset.y + axis2*offset.x + axis2*-offset.y + a_vertex;
-
+
gl_Position = transform * vec4(position, 1.0);
-
- v_los = position.xz * losTransform.x + losTransform.y;
+
+ calculateLOSCoordinates(position.xz);
+
v_tex = a_uv0;
v_color = a_color;
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.fs (revision 24732)
@@ -1,194 +1,191 @@
#version 120
#include "common/fog.h"
+#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
uniform sampler2D baseTex;
uniform sampler2D blendTex;
-uniform sampler2D losTex;
uniform sampler2D normTex;
uniform sampler2D specTex;
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec3 sunColor;
uniform vec3 sunDir;
uniform vec2 textureTransform;
varying vec3 v_lighting;
-varying vec2 v_los;
varying vec2 v_blend;
#if USE_TRIPLANAR
varying vec3 v_tex;
#else
varying vec2 v_tex;
#endif
#if USE_SPECULAR
uniform float specularPower;
uniform vec3 specularColor;
#endif
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_AO
uniform vec4 effectSettings;
#endif
varying vec3 v_normal;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP
#if USE_NORMAL_MAP
varying vec4 v_tangent;
varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#endif
#if USE_TRIPLANAR
vec4 triplanar(sampler2D sampler, vec3 wpos)
{
float tighten = 0.4679;
vec3 blending = abs(normalize(v_normal)) - tighten;
blending = max(blending, 0.0);
blending /= vec3(blending.x + blending.y + blending.z);
vec3 signedBlending = sign(v_normal) * blending;
vec3 coords = wpos;
coords.xyz /= 32.0; // Ugh.
vec4 col1 = texture2D(sampler, coords.yz);
vec4 col2 = texture2D(sampler, coords.zx);
vec4 col3 = texture2D(sampler, coords.yx);
vec4 colBlended = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return colBlended;
}
vec4 triplanarNormals(sampler2D sampler, vec3 wpos)
{
float tighten = 0.4679;
vec3 blending = abs(normalize(v_normal)) - tighten;
blending = max(blending, 0.0);
blending /= vec3(blending.x + blending.y + blending.z);
vec3 signedBlending = sign(v_normal) * blending;
vec3 coords = wpos;
coords.xyz /= 32.0; // Ugh.
vec4 col1 = texture2D(sampler, coords.yz).xyzw;
col1.y = 1.0 - col1.y;
vec4 col2 = texture2D(sampler, coords.zx).yxzw;
col2.y = 1.0 - col2.y;
vec4 col3 = texture2D(sampler, coords.yx).yxzw;
col3.y = 1.0 - col3.y;
vec4 colBlended = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return colBlended;
}
#endif
void main()
{
#if BLEND
// Use alpha from blend texture
gl_FragColor.a = 1.0 - texture2D(blendTex, v_blend).a;
#if USE_GRASS
if (gl_FragColor.a < LAYER / 10.0)
discard;
#endif
#else
gl_FragColor.a = 1.0;
#endif
#if USE_TRIPLANAR
vec4 tex = triplanar(baseTex, v_tex);
#else
vec4 tex = texture2D(baseTex, v_tex.xy);
#endif
#if USE_GRASS && LAYER
if (tex.a < 0.05)
discard;
#endif
#if DECAL
// Use alpha from main texture
gl_FragColor.a = tex.a;
#endif
vec3 texdiffuse = tex.rgb;
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP
vec3 normal = v_normal;
#endif
#if USE_NORMAL_MAP
float sign = v_tangent.w;
mat3 tbn = mat3(v_tangent.xyz, v_bitangent * -sign, v_normal);
#if USE_TRIPLANAR
vec3 ntex = triplanarNormals(normTex, v_tex).rgb * 2.0 - 1.0;
#else
vec3 ntex = texture2D(normTex, v_tex).rgb * 2.0 - 1.0;
#endif
normal = normalize(tbn * ntex);
vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
#else
vec3 sundiffuse = v_lighting;
#endif
vec4 specular = vec4(0.0);
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 specCol;
float specPow;
#if USE_SPECULAR_MAP
#if USE_TRIPLANAR
vec4 s = triplanar(specTex, v_tex);
#else
vec4 s = texture2D(specTex, v_tex);
#endif
specCol = s.rgb;
specular.a = s.a;
specPow = effectSettings.y;
#else
specCol = specularColor;
specPow = specularPower;
#endif
specular.rgb = sunColor * specCol * pow(max(0.0, dot(normalize(normal), v_half)), specPow);
#endif
vec3 color = (texdiffuse * sundiffuse + specular.rgb) * get_shadow() + texdiffuse * ambient;
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);
#endif
color = applyFog(color);
- float los = texture2D(losTex, v_los).a;
- los = los < 0.03 ? 0.0 : los;
- color *= los;
+ color *= getLOS();
#if DECAL
color *= shadingColor;
#endif
gl_FragColor.rgb = color;
#if USE_GRASS
gl_FragColor.a = tex.a;
#endif
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/terrain_common.vs (revision 24732)
@@ -1,106 +1,105 @@
#version 120
+#include "common/los_vertex.h"
#include "common/shadows_vertex.h"
uniform mat4 transform;
uniform vec3 cameraPos;
#ifdef GL_ES
uniform mediump vec3 sunDir;
uniform mediump vec3 sunColor;
#else
uniform vec3 sunDir;
uniform vec3 sunColor;
#endif
uniform vec2 textureTransform;
-uniform vec2 losTransform;
varying vec3 v_lighting;
-varying vec2 v_los;
varying vec2 v_blend;
#if USE_TRIPLANAR
varying vec3 v_tex;
#else
varying vec2 v_tex;
#endif
varying vec3 v_normal;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP
#if USE_NORMAL_MAP
varying vec4 v_tangent;
varying vec3 v_bitangent;
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
varying vec3 v_half;
#endif
#endif
attribute vec3 a_vertex;
attribute vec3 a_normal;
attribute vec2 a_uv0;
attribute vec2 a_uv1;
void main()
{
vec4 position = vec4(a_vertex, 1.0);
#if USE_GRASS && LAYER
position.y = a_vertex.y + (a_normal.y * 0.015 * LAYER);
#endif
gl_Position = transform * position;
v_lighting = clamp(-dot(a_normal, sunDir), 0.0, 1.0) * sunColor;
#if DECAL
v_tex.xy = a_uv0;
#else
#if USE_TRIPLANAR
v_tex = a_vertex;
#else
// Compute texcoords from position and terrain-texture-dependent transform
float c = textureTransform.x;
float s = -textureTransform.y;
v_tex = vec2(a_vertex.x * c + a_vertex.z * -s, a_vertex.x * -s + a_vertex.z * -c);
#endif
#if GL_ES
// XXX: Ugly hack to hide some precision issues in GLES
#if USE_TRIPLANAR
v_tex = mod(v_tex, vec3(9.0, 9.0, 9.0));
#else
v_tex = mod(v_tex, vec2(9.0, 9.0));
#endif
#endif
#endif
#if BLEND
v_blend = a_uv1;
#endif
calculatePositionInShadowSpace(vec4(a_vertex, 1.0));
v_normal = a_normal;
#if USE_SPECULAR || USE_NORMAL_MAP || USE_SPECULAR_MAP || USE_TRIPLANAR
#if USE_NORMAL_MAP
vec3 t = vec3(1.0, 0.0, 0.0);
t = normalize(t - v_normal * dot(v_normal, t));
v_tangent = vec4(t, -1.0);
v_bitangent = cross(v_normal, t);
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 eyeVec = cameraPos.xyz - position.xyz;
#if USE_SPECULAR || USE_SPECULAR_MAP
vec3 sunVec = -sunDir;
v_half = normalize(sunVec + normalize(eyeVec));
#endif
#endif
#endif
- v_los = a_vertex.xz * losTransform.x + losTransform.yy;
+ calculateLOSCoordinates(a_vertex.xz);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.fs (revision 24732)
@@ -1,335 +1,317 @@
#version 110
#include "common/fog.h"
-
+#include "common/los_fragment.h"
#include "common/shadows_fragment.h"
// Environment settings
uniform vec3 ambient;
uniform vec3 sunDir;
uniform vec3 sunColor;
uniform mat4 skyBoxRot;
uniform vec3 cameraPos;
-uniform sampler2D losTex;
-
uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture
uniform vec3 color; // color of the water
uniform vec3 tint; // Tint for refraction (used to simulate particles in water)
uniform float murkiness; // Amount of tint to blend in with the refracted color
uniform float windAngle;
varying vec2 WindCosSin;
uniform vec2 screenSize;
varying float moddedTime;
varying vec3 worldPos;
varying float waterDepth;
varying vec2 waterInfo;
varying vec3 v_eyeVec;
varying vec4 normalCoords;
#if USE_REFLECTION
varying vec3 reflectionCoords;
#endif
#if USE_REFRACTION
varying vec3 refractionCoords;
#endif
-varying vec2 losCoords;
varying float fwaviness;
uniform samplerCube skyCube;
uniform sampler2D normalMap;
uniform sampler2D normalMap2;
#if USE_FANCY_EFFECTS
uniform sampler2D waterEffectsTex;
#endif
uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump
uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement
#if USE_REFLECTION
uniform sampler2D reflectionMap;
#endif
#if USE_REFRACTION
uniform sampler2D refractionMap;
#if USE_REAL_DEPTH
uniform sampler2D depthTex;
uniform mat4 projInvTransform;
uniform mat4 viewInvTransform;
#endif
#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 ) );
-}
-
vec3 getNormal(vec4 fancyeffects)
{
float wavyEffect = waveParams1.r;
float baseScale = waveParams1.g;
float flattenism = waveParams1.b;
float baseBump = waveParams1.a;
float BigMovement = waveParams2.b;
// This method uses 60 animated water frames. We're blending between each two frames
// Scale the normal textures by waviness so that big waviness means bigger waves.
vec3 ww1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy;
vec3 ww2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).xzy;
vec3 wwInterp = mix(ww1, ww2, moddedTime) - vec3(0.5, 0.0, 0.5);
ww1.x = wwInterp.x * WindCosSin.x - wwInterp.z * WindCosSin.y;
ww1.z = wwInterp.x * WindCosSin.y + wwInterp.z * WindCosSin.x;
ww1.y = wwInterp.y;
// Flatten them based on waviness.
vec3 normal = normalize(mix(vec3(0.0, 1.0, 0.0), ww1, clamp(baseBump + fwaviness / flattenism, 0.0, 1.0)));
#if USE_FANCY_EFFECTS
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0);
normal.xz = mix(normal.xz, fancyeffects.rb, fancyeffects.a / 2.0);
#else
normal = mix(vec3(0.0, 1.0, 0.0), normal, 0.5 + waterInfo.r / 2.0);
#endif
return vec3(-normal.x, normal.y, -normal.z);
}
vec3 getSpecular(vec3 normal, vec3 eyeVec)
{
// Specular lighting vectors
vec3 specularVector = reflect(sunDir, normal);
// pow is undefined for null or negative values, except on intel it seems.
float specularIntensity = pow(max(dot(specularVector, eyeVec), 0.0), 100.0);
// Workaround to fix too flattened water.
specularIntensity = smoothstep(0.6, 1.0, specularIntensity) * 1.2;
return clamp(specularIntensity * sunColor, 0.0, 1.0);
}
vec4 getReflection(vec3 normal, vec3 eyeVec)
{
// Reflections
// 3 level of settings:
// -If a player has refraction and reflection disabled, we return a gradient of blue based on the Y component.
// -If a player has refraction OR reflection, we return a reflection of the actual skybox used.
// -If a player has reflection enabled, we also return a reflection of actual entities where applicable.
// reflMod reduces the intensity of reflections somewhat since they kind of wash refractions out otherwise.
float reflMod = 0.75;
vec3 eye = reflect(eyeVec, normal);
#if USE_REFLECTION
float refVY = clamp(eyeVec.y * 2.0, 0.05, 1.0);
// Distort the reflection coords based on waves.
vec2 reflCoords = (0.5 * reflectionCoords.xy - 15.0 * normal.zx / refVY) / reflectionCoords.z + 0.5;
vec4 refTex = texture2D(reflectionMap, reflCoords);
vec3 reflColor = refTex.rgb;
// Interpolate between the sky color and nearby objects.
// Only do this when alpha is rather low, or transparent leaves show up as extremely white.
if (refTex.a < 0.4)
reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a);
// Let actual objects be reflected fully.
reflMod = max(refTex.a, 0.75);
#elif USE_REFRACTION
vec3 reflColor = textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb;
#else // !USE_REFLECTION && !USE_REFRACTION
// Simplest case for reflection, return a gradient of blue based on Y component.
vec3 reflColor = mix(vec3(0.76, 0.84, 0.92), vec3(0.24, 0.43, 0.71), -eye.y);
#endif
return vec4(reflColor, reflMod);
}
#if USE_REFRACTION && USE_REAL_DEPTH
vec3 getWorldPositionFromRefractionDepth(vec2 uv)
{
float depth = texture2D(depthTex, uv).x;
vec4 viewPosition = projInvTransform * (vec4((uv - vec2(0.5)) * 2.0, depth * 2.0 - 1.0, 1.0));
viewPosition /= viewPosition.w;
vec3 refrWorldPos = (viewInvTransform * viewPosition).xyz;
// Depth buffer precision errors can give heights above the water.
refrWorldPos.y = min(refrWorldPos.y, worldPos.y);
return refrWorldPos;
}
#endif
vec4 getRefraction(vec3 normal, vec3 eyeVec, float depthLimit)
{
#if USE_REFRACTION && USE_REAL_DEPTH
// Compute real depth at the target point.
vec2 coords = (0.5 * refractionCoords.xy) / refractionCoords.z + 0.5;
vec3 refrWorldPos = getWorldPositionFromRefractionDepth(coords);
// Set depth to the depth at the undistorted point.
float depth = distance(refrWorldPos, worldPos);
#else
// fake depth computation: take the value at the vertex, add some if we are looking at a more oblique angle.
float depth = waterDepth / (min(0.5, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0);
#endif
#if USE_REFRACTION
// for refraction we want to distort more as depth goes down.
// 1) compute a distortion based on depth at the pixel.
// 2) Re-sample the depth at the target point
// 3) Sample refraction texture
// distoFactor controls the amount of distortion relative to wave normals.
float distoFactor = 0.5 + clamp(depth / 2.0, 0.0, 7.0);
#if USE_REAL_DEPTH
// Distort the texture coords under where the water is to simulate refraction.
vec2 shiftedCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5;
vec3 refrWorldPos2 = getWorldPositionFromRefractionDepth(shiftedCoords);
float newDepth = distance(refrWorldPos2, worldPos);
// try to correct for fish. In general they'd look weirder without this fix.
if (depth > newDepth + 3.0)
distoFactor /= 2.0; // this in general will not fall on the fish but still look distorted.
else
depth = newDepth;
#endif
#if USE_FANCY_EFFECTS
depth = max(depth, depthLimit);
if (waterDepth < 0.0)
depth = 0.0;
#endif
// Distort the texture coords under where the water is to simulate refraction.
vec2 refrCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5;
vec3 refColor = texture2D(refractionMap, refrCoords).rgb;
// Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red.
// If we get a pure red fragment, use an undistorted/less distorted coord instead.
// blur the refraction map, distoring using normal so that it looks more random than it really is
// and thus looks much better.
float blur = (0.1 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z;
vec4 blurColor = vec4(refColor, 1.0);
vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.x, blur + normal.z));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + normal.z));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + normal.x));
blurColor += vec4(tex.rgb * tex.a, tex.a);
tex = texture2D(refractionMap, refrCoords + vec2(blur + normal.z, -blur));
blurColor += vec4(tex.rgb * tex.a, tex.a);
blurColor /= blurColor.a;
float blurFactor = (distoFactor / 7.0);
refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor);
#else // !USE_REFRACTION
#if USE_FANCY_EFFECTS
depth = max(depth, depthLimit);
#endif
vec3 refColor = color;
#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 = max(eyeVec.y, 0.01);
float murky = mix(200.0, 0.1, pow(murkiness, 0.25));
// Apply water tint and murk color.
float extFact = max(0.0, 1.0 - (depth * fixedVy / murky));
float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky));
vec3 colll = mix(refColor * tint, refColor, ColextFact);
vec3 refrColor = mix(color, colll, extFact);
float alpha = clamp(depth, 0.0, 1.0);
#if !USE_REFRACTION
alpha = (1.4 - extFact) * alpha;
#endif
return vec4(refrColor, alpha);
}
vec4 getFoam(vec4 fancyeffects, float shadow)
{
#if USE_FANCY_EFFECTS
float wavyEffect = waveParams1.r;
float baseScale = waveParams1.g;
float BigMovement = waveParams2.b;
vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa;
vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa;
vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa;
vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa;
vec3 foaminterp = mix(foam1, foam2, moddedTime);
foaminterp *= mix(foam3, foam4, moddedTime);
foam1.x = abs(foaminterp.x * WindCosSin.x) + abs(foaminterp.z * WindCosSin.y);
float alpha = (fancyeffects.g + pow(foam1.x * (3.0 + waviness), 2.6 - waviness / 5.5)) * 2.0;
return vec4(sunColor * shadow + ambient, clamp(alpha, 0.0, 1.0));
#else
return vec4(0.0);
#endif
}
void main()
{
#if USE_FANCY_EFFECTS
vec4 fancyeffects = texture2D(waterEffectsTex, gl_FragCoord.xy / screenSize);
#else
vec4 fancyeffects = vec4(0.0);
#endif
vec3 eyeVec = normalize(v_eyeVec);
vec3 normal = getNormal(fancyeffects);
vec4 refrColor = getRefraction(normal, eyeVec, fancyeffects.a);
vec4 reflColor = getReflection(normal, eyeVec);
// How perpendicular to the normal our view is. Used for fresnel.
float ndotv = clamp(dot(normal, eyeVec), 0.0, 1.0);
// Fresnel for "how much reflection vs how much refraction".
float fresnel = clamp(((pow(1.1 - ndotv, 2.0)) * 1.5), 0.1, 0.75); // Approximation. I'm using 1.1 and not 1.0 because it causes artifacts, see #1714
vec3 specular = getSpecular(normal, eyeVec);
#if USE_SHADOW
float shadow = get_shadow();
- float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2);
+ float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + 10.0 * murkiness * 0.2);
+ fresShadow = fresnel;
vec3 color = mix(refrColor.rgb, reflColor.rgb, fresShadow * reflColor.a);
color += shadow * specular;
+ //color = vec3(fresShadow);
vec4 foam = getFoam(fancyeffects, shadow);
#else
vec3 color = mix(refrColor.rgb, reflColor.rgb, fresnel * reflColor.a);
color += specular;
vec4 foam = getFoam(fancyeffects, 1.0);
#endif
color = clamp(mix(color, foam.rgb, foam.a), 0.0, 1.0);
color = applyFog(color);
- float alpha = refrColor.a;
- float losMod = texture2D(losTex, losCoords.st).a;
- losMod = losMod < 0.03 ? 0.0 : losMod;
- gl_FragColor = vec4(color * losMod, alpha);
+ gl_FragColor = vec4(color * getLOS(), refrColor.a);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/water_high.vs (revision 24732)
@@ -1,75 +1,74 @@
#version 110
+#include "common/los_vertex.h"
#include "common/shadows_vertex.h"
uniform mat4 reflectionMatrix;
uniform mat4 refractionMatrix;
-uniform mat4 losMatrix;
uniform float repeatScale;
uniform float windAngle;
// "Wildness" of the reflections and refractions; choose based on texture
uniform float waviness;
uniform vec3 sunDir;
uniform float time;
uniform mat4 transform;
uniform vec3 cameraPos;
varying float moddedTime;
varying vec3 worldPos;
varying float waterDepth;
varying vec2 waterInfo;
varying vec3 v_eyeVec;
varying vec4 normalCoords;
#if USE_REFLECTION
varying vec3 reflectionCoords;
#endif
#if USE_REFRACTION
varying vec3 refractionCoords;
#endif
-varying vec2 losCoords;
varying float fwaviness;
varying vec2 WindCosSin;
attribute vec3 a_vertex;
attribute vec2 a_waterInfo;
attribute vec3 a_otherPosition;
void main()
{
worldPos = a_vertex;
waterInfo = a_waterInfo;
waterDepth = a_waterInfo.g;
WindCosSin = vec2(cos(-windAngle), sin(-windAngle));
float newX = a_vertex.x * WindCosSin.x - a_vertex.z * WindCosSin.y;
float newY = a_vertex.x * WindCosSin.y + a_vertex.z * WindCosSin.x;
normalCoords = vec4(newX, newY, time, 0.0);
normalCoords.xy *= repeatScale;
// Projective texturing
#if USE_REFLECTION
reflectionCoords = (reflectionMatrix * vec4(a_vertex, 1.0)).rga;
#endif
#if USE_REFRACTION
refractionCoords = (refractionMatrix * vec4(a_vertex, 1.0)).rga;
#endif
- losCoords = (losMatrix * vec4(a_vertex, 1.0)).rg;
+ calculateLOSCoordinates(a_vertex.xz);
calculatePositionInShadowSpace(vec4(a_vertex, 1.0));
v_eyeVec = normalize(cameraPos - worldPos);
moddedTime = mod(time * 60.0, 8.0) / 8.0;
// Fix the waviness for local wind strength
fwaviness = waviness * (0.15 + a_waterInfo.r / 1.15);
gl_Position = transform * vec4(a_vertex, 1.0);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.fs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.fs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.fs (revision 24732)
@@ -1,15 +1,13 @@
#version 110
+#include "common/los_fragment.h"
+
uniform sampler2D baseTex;
-uniform sampler2D losTex;
uniform vec3 color;
varying vec2 v_coords;
-varying vec2 v_losCoords;
void main()
{
- float losMod = texture2D(losTex, v_losCoords.st).a;
- losMod = losMod < 0.03 ? 0.0 : losMod;
- gl_FragColor = vec4(texture2D(baseTex, v_coords).rgb * color * losMod, 1.0);
+ gl_FragColor = vec4(texture2D(baseTex, v_coords).rgb * color * getLOS(), 1.0);
}
Index: ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.vs
===================================================================
--- ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.vs (revision 24731)
+++ ps/trunk/binaries/data/mods/public/shaders/glsl/water_simple.vs (revision 24732)
@@ -1,22 +1,22 @@
#version 110
+#include "common/los_vertex.h"
+
attribute vec3 a_vertex;
uniform mat4 transform;
-uniform mat4 losMatrix;
uniform float time;
varying vec2 v_coords;
-varying vec2 v_losCoords;
void main()
{
// Shift the texture coordinates by these amounts to make the water "flow"
float tx = -mod(time, 81.0) / 81.0;
float tz = -mod(time, 34.0) / 34.0;
float repeatPeriod = 16.0;
v_coords = a_vertex.xz / repeatPeriod + vec2(tx, tz);
- v_losCoords = (losMatrix * vec4(a_vertex, 1.0)).rg;
+ calculateLOSCoordinates(a_vertex.xz);
gl_Position = transform * vec4(a_vertex, 1.0);
}
Index: ps/trunk/source/ps/CStrInternStatic.h
===================================================================
--- ps/trunk/source/ps/CStrInternStatic.h (revision 24731)
+++ ps/trunk/source/ps/CStrInternStatic.h (revision 24732)
@@ -1,166 +1,165 @@
-/* Copyright (C) 2020 Wildfire Games.
+/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
// This file defines global CStrIntern variables, to avoid the cost of
// constructing CStrInterns frequently at runtime.
//
// A line like
// X(foo)
// defines a variable str_foo with value "foo".
//
// A line like
// X2(foo_0, "foo[0]")
// defines a variable str_foo_0 with value "foo[0]".
X(0)
X(1)
X(2)
X(ALPHABLEND_PASS_BLEND)
X(ALPHABLEND_PASS_OPAQUE)
X(BLEND)
X(BLOOM_NOP)
X(BLOOM_PASS_H)
X(BLOOM_PASS_V)
X(DECAL)
X(DISABLE_RECEIVE_SHADOWS)
X(IGNORE_LOS)
X(MINIMAP_BASE)
X(MINIMAP_LINE)
X(MINIMAP_LOS)
X(MINIMAP_MASK)
X(MINIMAP_POINT)
X(MODE_SHADOWCAST)
X(MODE_SILHOUETTEDISPLAY)
X(MODE_SILHOUETTEOCCLUDER)
X(MODE_WIREFRAME)
X(SYS_HAS_ARB)
X(SYS_HAS_GLSL)
X(SYS_PREFER_GLSL)
X(USE_FANCY_EFFECTS)
X(USE_FP_SHADOW)
X(USE_GPU_SKINNING)
X(USE_INSTANCING)
X(USE_NORMALS)
X(USE_OBJECTCOLOR)
X(USE_REAL_DEPTH)
X(USE_REFLECTION)
X(USE_REFRACTION)
X(USE_SHADOW)
X(USE_SHADOW_PCF)
X(USE_SHADOW_SAMPLER)
X(USE_FOG)
X(WATERTYPE_CLAP)
X(WATERTYPE_LAKE)
X2(_emptystring, "")
X(a_apexPosition)
X(a_otherPosition)
X(a_retreatPosition)
X(a_skinJoints)
X(a_skinWeights)
X(a_splashPosition)
X(a_tangent)
X(a_waterInfo)
X(ambient)
X(baseTex)
X(blendTex)
X(bloom)
X(blurTex2)
X(blurTex4)
X(blurTex8)
X(brightness)
X(cameraPos)
X(color)
X(colorAdd)
X(colorMul)
X(debug_overlay)
X(delta)
X(depthTex)
X(foamTex)
X(fogColor)
X(fogParams)
X(foreground_overlay)
X(gui_add)
X(gui_basic)
X(gui_grayscale)
X(gui_solid)
X(gui_solid_mask)
X(gui_text)
X(hdr)
X(height)
X(instancingTransform)
-X(losMatrix)
X(losTex)
X(losTex1)
X(losTex2)
X(losTransform)
X(los_interp)
X(mapSize)
X(maskTex)
X(maskTextureTransform)
X(minimap)
X(modelViewMatrix)
X(murkiness)
X(normalMap)
X(normalMap2)
X(objectColor)
X(overlay_solid)
X(particle)
X(particle_solid)
X(playerColor)
X(pointSize)
X(projInvTransform)
X(qualityLevel)
X(reflectionMap)
X(reflectionMatrix)
X(refractionMap)
X(refractionMatrix)
X(renderedTex)
X(repeatScale)
X2(sans_10, "sans-10");
X(saturation)
X(screenSize)
X(shadingColor)
X(shadowScale)
X(shadowTex)
X(shadowTransform)
X(sharpness)
X(skinBlendMatrices)
X2(skinBlendMatrices_0, "skinBlendMatrices[0]")
X(skyBoxRot)
X(skyCube)
X(sky_simple)
X(sunColor)
X(sunDir)
X(tex)
X(texSize)
X(textureTransform)
X(time)
X(tint)
X(transform)
X(translation)
X(viewInvTransform)
X(water_simple)
X(waterEffectsTex)
X(waterTex)
X(waveTex)
X(waviness)
X(waveParams1)
X(waveParams2)
X(width)
X(windAngle)
X(zFar)
X(zNear)
Index: ps/trunk/source/renderer/TerrainRenderer.cpp
===================================================================
--- ps/trunk/source/renderer/TerrainRenderer.cpp (revision 24731)
+++ ps/trunk/source/renderer/TerrainRenderer.cpp (revision 24732)
@@ -1,696 +1,696 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/*
* Terrain rendering (everything related to patches and water) is
* encapsulated in TerrainRenderer
*/
#include "precompiled.h"
#include "graphics/Camera.h"
#include "graphics/Decal.h"
#include "graphics/LightEnv.h"
#include "graphics/LOSTexture.h"
#include "graphics/Patch.h"
#include "graphics/GameView.h"
#include "graphics/Model.h"
#include "graphics/ShaderManager.h"
#include "renderer/ShadowMap.h"
#include "renderer/SkyManager.h"
#include "graphics/TerritoryTexture.h"
#include "graphics/TextRenderer.h"
#include "maths/MathUtil.h"
#include "ps/Filesystem.h"
#include "ps/CLogger.h"
#include "ps/Game.h"
#include "ps/Profile.h"
#include "ps/World.h"
#include "renderer/DecalRData.h"
#include "renderer/PatchRData.h"
#include "renderer/Renderer.h"
#include "renderer/RenderingOptions.h"
#include "renderer/ShadowMap.h"
#include "renderer/TerrainRenderer.h"
#include "renderer/VertexArray.h"
#include "renderer/WaterManager.h"
#include "tools/atlas/GameInterface/GameLoop.h"
extern GameLoopState* g_AtlasGameLoop;
///////////////////////////////////////////////////////////////////////////////////////////////
// TerrainRenderer implementation
namespace
{
CShaderProgramPtr GetDummyShader()
{
const char* shaderName;
if (g_RenderingOptions.GetPreferGLSL())
shaderName = "glsl/dummy";
else
shaderName = "arb/dummy";
return g_Renderer.GetShaderManager().LoadProgram(shaderName, CShaderDefines());
}
} // anonymous namespace
/**
* TerrainRenderer keeps track of which phase it is in, to detect
* when Submit, PrepareForRendering etc. are called in the wrong order.
*/
enum Phase {
Phase_Submit,
Phase_Render
};
/**
* Struct TerrainRendererInternals: Internal variables used by the TerrainRenderer class.
*/
struct TerrainRendererInternals
{
/// Which phase (submitting or rendering patches) are we in right now?
Phase phase;
/// Patches that were submitted for this frame
std::vector visiblePatches[CRenderer::CULL_MAX];
/// Decals that were submitted for this frame
std::vector visibleDecals[CRenderer::CULL_MAX];
/// Fancy water shader
CShaderProgramPtr fancyWaterShader;
CSimulation2* simulation;
};
///////////////////////////////////////////////////////////////////
// Construction/Destruction
TerrainRenderer::TerrainRenderer()
{
m = new TerrainRendererInternals();
m->phase = Phase_Submit;
}
TerrainRenderer::~TerrainRenderer()
{
delete m;
}
void TerrainRenderer::SetSimulation(CSimulation2* simulation)
{
m->simulation = simulation;
}
///////////////////////////////////////////////////////////////////
// Submit a patch for rendering
void TerrainRenderer::Submit(int cullGroup, CPatch* patch)
{
ENSURE(m->phase == Phase_Submit);
CPatchRData* data = (CPatchRData*)patch->GetRenderData();
if (data == 0)
{
// no renderdata for patch, create it now
data = new CPatchRData(patch, m->simulation);
patch->SetRenderData(data);
}
data->Update(m->simulation);
m->visiblePatches[cullGroup].push_back(data);
}
///////////////////////////////////////////////////////////////////
// Submit a decal for rendering
void TerrainRenderer::Submit(int cullGroup, CModelDecal* decal)
{
ENSURE(m->phase == Phase_Submit);
CDecalRData* data = (CDecalRData*)decal->GetRenderData();
if (data == 0)
{
// no renderdata for decal, create it now
data = new CDecalRData(decal, m->simulation);
decal->SetRenderData(data);
}
data->Update(m->simulation);
m->visibleDecals[cullGroup].push_back(data);
}
///////////////////////////////////////////////////////////////////
// Prepare for rendering
void TerrainRenderer::PrepareForRendering()
{
ENSURE(m->phase == Phase_Submit);
m->phase = Phase_Render;
}
///////////////////////////////////////////////////////////////////
// Clear submissions lists
void TerrainRenderer::EndFrame()
{
ENSURE(m->phase == Phase_Render || m->phase == Phase_Submit);
for (int i = 0; i < CRenderer::CULL_MAX; ++i)
{
m->visiblePatches[i].clear();
m->visibleDecals[i].clear();
}
m->phase = Phase_Submit;
}
void TerrainRenderer::RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& textureMatrix, GLuint texture)
{
#if CONFIG2_GLES
#warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES
UNUSED2(cullGroup);
UNUSED2(textureMatrix);
UNUSED2(texture);
#else
ENSURE(m->phase == Phase_Render);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(0);
glDisable(GL_DEPTH_TEST);
CShaderTechniquePtr debugOverlayTech =
g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay);
debugOverlayTech->BeginPass();
CShaderProgramPtr debugOverlayShader = debugOverlayTech->GetShader();
debugOverlayShader->Bind();
debugOverlayShader->BindTexture(str_baseTex, texture);
debugOverlayShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
debugOverlayShader->Uniform(str_textureTransform, textureMatrix);
CPatchRData::RenderStreams(visiblePatches, debugOverlayShader, STREAM_POS | STREAM_POSTOUV0);
glEnable(GL_DEPTH_TEST);
// To make the overlay visible over water, render an additional map-sized
// water-height patch.
CBoundingBoxAligned waterBounds;
for (CPatchRData* data : visiblePatches)
waterBounds += data->GetWaterBounds();
if (!waterBounds.IsEmpty())
{
// Add a delta to avoid z-fighting.
const float height = g_Renderer.GetWaterManager()->m_WaterHeight + 0.05f;
const float waterPos[] = {
waterBounds[0].X, height, waterBounds[0].Z,
waterBounds[1].X, height, waterBounds[0].Z,
waterBounds[0].X, height, waterBounds[1].Z,
waterBounds[1].X, height, waterBounds[1].Z
};
const GLsizei stride = sizeof(float) * 3;
debugOverlayShader->VertexPointer(3, GL_FLOAT, stride, waterPos);
debugOverlayShader->TexCoordPointer(GL_TEXTURE0, 3, GL_FLOAT, stride, waterPos);
debugOverlayShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
debugOverlayShader->Unbind();
debugOverlayTech->EndPass();
glDepthMask(1);
glDisable(GL_BLEND);
#endif
}
///////////////////////////////////////////////////////////////////
/**
* Set up all the uniforms for a shader pass.
*/
void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow)
{
shader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
shader->Uniform(str_cameraPos, g_Renderer.GetViewCamera().GetOrientation().GetTranslation());
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
if (shadow)
shadow->BindTo(shader);
CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
shader->BindTexture(str_losTex, los.GetTextureSmooth());
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
shader->Uniform(str_ambient, lightEnv.m_AmbientColor);
shader->Uniform(str_sunColor, lightEnv.m_SunColor);
shader->Uniform(str_sunDir, lightEnv.GetSunDir());
shader->Uniform(str_fogColor, lightEnv.m_FogColor);
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
}
void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
{
ENSURE(m->phase == Phase_Render);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
std::vector& visibleDecals = m->visibleDecals[cullGroup];
if (visiblePatches.empty() && visibleDecals.empty())
return;
// render the solid black sides of the map first
CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
techSolid->BeginPass();
CShaderProgramPtr shaderSolid = techSolid->GetShader();
shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
PROFILE_START("render terrain sides");
for (size_t i = 0; i < visiblePatches.size(); ++i)
visiblePatches[i]->RenderSides(shaderSolid);
PROFILE_END("render terrain sides");
techSolid->EndPass();
PROFILE_START("render terrain base");
CPatchRData::RenderBases(visiblePatches, context, shadow);
PROFILE_END("render terrain base");
// no need to write to the depth buffer a second time
glDepthMask(0);
// render blend passes for each patch
PROFILE_START("render terrain blends");
CPatchRData::RenderBlends(visiblePatches, context, shadow, false);
PROFILE_END("render terrain blends");
PROFILE_START("render terrain decals");
CDecalRData::RenderDecals(visibleDecals, context, shadow, false);
PROFILE_END("render terrain decals");
// restore OpenGL state
g_Renderer.BindTexture(1, 0);
g_Renderer.BindTexture(2, 0);
g_Renderer.BindTexture(3, 0);
glDepthMask(1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
}
///////////////////////////////////////////////////////////////////
// Render un-textured patches as polygons
void TerrainRenderer::RenderPatches(int cullGroup, const CColor& color)
{
ENSURE(m->phase == Phase_Render);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
if (visiblePatches.empty())
return;
#if CONFIG2_GLES
#warning TODO: implement TerrainRenderer::RenderPatches for GLES
#else
CShaderProgramPtr dummyShader = GetDummyShader();
dummyShader->Bind();
dummyShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
dummyShader->Uniform(str_color, color);
glEnableClientState(GL_VERTEX_ARRAY);
CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS);
glDisableClientState(GL_VERTEX_ARRAY);
dummyShader->Unbind();
#endif
}
///////////////////////////////////////////////////////////////////
// Render outlines of submitted patches as lines
void TerrainRenderer::RenderOutlines(int cullGroup)
{
ENSURE(m->phase == Phase_Render);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
if (visiblePatches.empty())
return;
#if CONFIG2_GLES
#warning TODO: implement TerrainRenderer::RenderOutlines for GLES
#else
glEnableClientState(GL_VERTEX_ARRAY);
for (size_t i = 0; i < visiblePatches.size(); ++i)
visiblePatches[i]->RenderOutline();
glDisableClientState(GL_VERTEX_ARRAY);
#endif
}
///////////////////////////////////////////////////////////////////
// Scissor rectangle of water patches
CBoundingBoxAligned TerrainRenderer::ScissorWater(int cullGroup, const CMatrix3D &viewproj)
{
std::vector& visiblePatches = m->visiblePatches[cullGroup];
CBoundingBoxAligned scissor;
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
const CBoundingBoxAligned& waterBounds = data->GetWaterBounds();
if (waterBounds.IsEmpty())
continue;
CVector4D v1 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
CVector4D v2 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
CVector4D v3 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
CVector4D v4 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
CBoundingBoxAligned screenBounds;
#define ADDBOUND(v1, v2, v3, v4) \
if (v1.Z >= -v1.W) \
screenBounds += CVector3D(v1.X, v1.Y, v1.Z) * (1.0f / v1.W); \
else \
{ \
float t = v1.Z + v1.W; \
if (v2.Z > -v2.W) \
{ \
CVector4D c2 = v1 + (v2 - v1) * (t / (t - (v2.Z + v2.W))); \
screenBounds += CVector3D(c2.X, c2.Y, c2.Z) * (1.0f / c2.W); \
} \
if (v3.Z > -v3.W) \
{ \
CVector4D c3 = v1 + (v3 - v1) * (t / (t - (v3.Z + v3.W))); \
screenBounds += CVector3D(c3.X, c3.Y, c3.Z) * (1.0f / c3.W); \
} \
if (v4.Z > -v4.W) \
{ \
CVector4D c4 = v1 + (v4 - v1) * (t / (t - (v4.Z + v4.W))); \
screenBounds += CVector3D(c4.X, c4.Y, c4.Z) * (1.0f / c4.W); \
} \
}
ADDBOUND(v1, v2, v3, v4);
ADDBOUND(v2, v1, v3, v4);
ADDBOUND(v3, v1, v2, v4);
ADDBOUND(v4, v1, v2, v3);
#undef ADDBOUND
if (screenBounds[0].X >= 1.0f || screenBounds[1].X <= -1.0f || screenBounds[0].Y >= 1.0f || screenBounds[1].Y <= -1.0f)
continue;
scissor += screenBounds;
}
return CBoundingBoxAligned(CVector3D(Clamp(scissor[0].X, -1.0f, 1.0f), Clamp(scissor[0].Y, -1.0f, 1.0f), -1.0f),
CVector3D(Clamp(scissor[1].X, -1.0f, 1.0f), Clamp(scissor[1].Y, -1.0f, 1.0f), 1.0f));
}
// Render fancy water
bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
{
PROFILE3_GPU("fancy water");
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
CShaderDefines defines = context;
// If we're using fancy water, make sure its shader is loaded
if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading)
{
if (WaterMgr->m_WaterRealDepth)
defines.Add(str_USE_REAL_DEPTH, 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);
// haven't updated the ARB shader yet so I'll always load the GLSL
/*if (!g_RenderingOptions.GetPreferGLSL() && !superFancy)
m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("arb/water_high", defines);
else*/
m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_high", defines);
if (!m->fancyWaterShader)
{
LOGERROR("Failed to load water shader. Falling back to fixed pipeline water.\n");
WaterMgr->m_RenderWater = false;
return false;
}
WaterMgr->m_NeedsReloading = false;
}
CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
// Calculating the advanced informations about Foam and all if the quality calls for it.
/*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
{
WaterMgr->m_NeedInfoUpdate = false;
WaterMgr->CreateSuperfancyInfo();
}*/
double time = WaterMgr->m_WaterTexTimer;
double period = 8;
int curTex = (int)(time*60/period) % 60;
int nexTex = (curTex + 1) % 60;
float repeatPeriod = WaterMgr->m_RepeatPeriod;
// 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);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, WaterMgr->m_FancyEffectsFBO);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
// Overwrite waves that would be behind the ground.
CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("glsl/gui_solid", CShaderDefines());
dummyShader->Bind();
dummyShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
data->RenderWater(dummyShader, true, true);
}
dummyShader->Unbind();
glEnable(GL_CULL_FACE);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
}
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();
m->fancyWaterShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]);
m->fancyWaterShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]);
if (WaterMgr->m_WaterFancyEffects)
{
m->fancyWaterShader->BindTexture(str_waterEffectsTex, WaterMgr->m_FancyTexture);
}
if (WaterMgr->m_WaterRefraction && WaterMgr->m_WaterRealDepth)
{
m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_RefrFboDepthTexture);
m->fancyWaterShader->Uniform(str_projInvTransform, WaterMgr->m_RefractionProjInvMatrix);
m->fancyWaterShader->Uniform(str_viewInvTransform, WaterMgr->m_RefractionViewInvMatrix);
}
if (WaterMgr->m_WaterRefraction)
m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture);
if (WaterMgr->m_WaterReflection)
m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture);
m->fancyWaterShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
m->fancyWaterShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
//TODO: bind only what's needed
if (WaterMgr->m_WaterRefraction || WaterMgr->m_WaterReflection)
{
m->fancyWaterShader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube());
// TODO: check that this rotates in the right direction.
CMatrix3D skyBoxRotation;
skyBoxRotation.SetIdentity();
skyBoxRotation.RotateY(M_PI + lightEnv.GetRotation());
m->fancyWaterShader->Uniform(str_skyBoxRot, skyBoxRotation);
if (WaterMgr->m_WaterRefraction)
m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix);
if (WaterMgr->m_WaterReflection)
m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix);
}
m->fancyWaterShader->Uniform(str_ambient, lightEnv.m_AmbientColor);
m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir());
m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor);
m->fancyWaterShader->Uniform(str_color, WaterMgr->m_WaterColor);
m->fancyWaterShader->Uniform(str_tint, WaterMgr->m_WaterTint);
m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness);
m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness);
m->fancyWaterShader->Uniform(str_windAngle, WaterMgr->m_WindAngle);
m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
- m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix());
+ m->fancyWaterShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
m->fancyWaterShader->Uniform(str_cameraPos, camera.GetOrientation().GetTranslation());
m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);
m->fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
m->fancyWaterShader->Uniform(str_time, (float)time);
m->fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
if (WaterMgr->m_WaterType == L"clap")
{
m->fancyWaterShader->Uniform(str_waveParams1, 30.0f,1.5f,20.0f,0.03f);
m->fancyWaterShader->Uniform(str_waveParams2, 0.5f,0.0f,0.0f,0.0f);
}
else if (WaterMgr->m_WaterType == L"lake")
{
m->fancyWaterShader->Uniform(str_waveParams1, 8.5f,1.5f,15.0f,0.03f);
m->fancyWaterShader->Uniform(str_waveParams2, 0.2f,0.0f,0.0f,0.07f);
}
else
{
m->fancyWaterShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f);
m->fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f);
}
if (shadow)
shadow->BindTo(m->fancyWaterShader);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
data->RenderWater(m->fancyWaterShader);
}
m->fancyWaterShader->Unbind();
glDepthFunc(GL_LEQUAL);
glDisable(GL_BLEND);
return true;
}
void TerrainRenderer::RenderSimpleWater(int cullGroup)
{
#if CONFIG2_GLES
UNUSED2(cullGroup);
#else
PROFILE3_GPU("simple water");
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
double time = WaterMgr->m_WaterTexTimer;
double period = 1.6f;
int curTex = (int)(time*60/period) % 60;
CShaderTechniquePtr waterSimpleTech =
g_Renderer.GetShaderManager().LoadEffect(str_water_simple);
waterSimpleTech->BeginPass();
CShaderProgramPtr waterSimpleShader = waterSimpleTech->GetShader();
waterSimpleShader->Bind();
waterSimpleShader->BindTexture(str_baseTex, WaterMgr->m_WaterTexture[curTex]);
waterSimpleShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
waterSimpleShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
- waterSimpleShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix());
+ waterSimpleShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
waterSimpleShader->Uniform(str_time, static_cast(time));
waterSimpleShader->Uniform(str_color, WaterMgr->m_WaterColor);
glEnableClientState(GL_VERTEX_ARRAY);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
data->RenderWater(waterSimpleShader, false, true);
}
glDisableClientState(GL_VERTEX_ARRAY);
waterSimpleShader->Unbind();
g_Renderer.BindTexture(1, 0);
pglActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
waterSimpleTech->EndPass();
#endif
}
///////////////////////////////////////////////////////////////////
// Render water that is part of the terrain
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
{
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
WaterMgr->UpdateQuality();
if (!WaterMgr->WillRenderFancyWater())
RenderSimpleWater(cullGroup);
else
RenderFancyWater(context, cullGroup, shadow);
}
void TerrainRenderer::RenderPriorities(int cullGroup)
{
PROFILE("priorities");
ENSURE(m->phase == Phase_Render);
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
tech->BeginPass();
CTextRenderer textRenderer(tech->GetShader());
textRenderer.Font(CStrIntern("mono-stroke-10"));
textRenderer.Color(1.0f, 1.0f, 0.0f);
std::vector& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
visiblePatches[i]->RenderPriorities(textRenderer);
textRenderer.Render();
tech->EndPass();
}