Water and waterfall shaders, materials and examples.
This was SVN commit r12643.
This commit is contained in:
parent
1fec7c382b
commit
779a33ee30
19
binaries/data/mods/public/art/actors/temp/reservoir.xml
Normal file
19
binaries/data/mods/public/art/actors/temp/reservoir.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<actor version="1">
|
||||||
|
|
||||||
|
<castshadow/>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<variant frequency="100" name="Base">
|
||||||
|
<animations/>
|
||||||
|
<mesh>test/reservoir.dae</mesh>
|
||||||
|
<props>
|
||||||
|
<prop actor="temp/reservoir_water.xml" attachpoint="root"/>
|
||||||
|
</props>
|
||||||
|
<textures>
|
||||||
|
<texture file="structural/rome_struct.png" name="baseTex"/>
|
||||||
|
</textures>
|
||||||
|
</variant>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</actor>
|
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<actor version="1">
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<variant frequency="100" name="Base">
|
||||||
|
<animations/>
|
||||||
|
<mesh>test/reservoir-water.dae</mesh>
|
||||||
|
<props/>
|
||||||
|
<textures>
|
||||||
|
<texture file="structural/rome_struct.png" name="baseTex"/>
|
||||||
|
</textures>
|
||||||
|
</variant>
|
||||||
|
</group>
|
||||||
|
<material>player_water.xml</material>
|
||||||
|
|
||||||
|
</actor>
|
16
binaries/data/mods/public/art/actors/temp/water_plane.xml
Normal file
16
binaries/data/mods/public/art/actors/temp/water_plane.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<actor version="1">
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<variant frequency="100" name="water_plane">
|
||||||
|
<animations/>
|
||||||
|
<mesh>test/waterplane.dae</mesh>
|
||||||
|
<props/>
|
||||||
|
<textures>
|
||||||
|
<texture file="structural/rome_struct.png" name="baseTex"/>
|
||||||
|
</textures>
|
||||||
|
</variant>
|
||||||
|
</group>
|
||||||
|
<material>player_water.xml</material>
|
||||||
|
|
||||||
|
</actor>
|
16
binaries/data/mods/public/art/actors/temp/waterfall.xml
Normal file
16
binaries/data/mods/public/art/actors/temp/waterfall.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<actor version="1">
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<variant frequency="100" name="waterfall">
|
||||||
|
<animations/>
|
||||||
|
<mesh>test/waterfall.dae</mesh>
|
||||||
|
<props/>
|
||||||
|
<textures>
|
||||||
|
<texture file="temp/waterfall.png" name="baseTex"/>
|
||||||
|
</textures>
|
||||||
|
</variant>
|
||||||
|
</group>
|
||||||
|
<material>waterfall.xml</material>
|
||||||
|
|
||||||
|
</actor>
|
@ -3,7 +3,7 @@
|
|||||||
<shader effect="model_transparent"/>
|
<shader effect="model_transparent"/>
|
||||||
<alpha_blending/>
|
<alpha_blending/>
|
||||||
<define name="USE_TRANSPARENT" value="1"/>
|
<define name="USE_TRANSPARENT" value="1"/>
|
||||||
<renderquery name="time"/>
|
<renderquery name="sim_time"/>
|
||||||
<define name="USE_WIND" value="1"/>
|
<define name="USE_WIND" value="1"/>
|
||||||
<uniform name="windData" value="1.0 1.0"/>
|
<uniform name="windData" value="1.0 1.0"/>
|
||||||
</material>
|
</material>
|
||||||
|
16
binaries/data/mods/public/art/materials/player_water.xml
Normal file
16
binaries/data/mods/public/art/materials/player_water.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<material>
|
||||||
|
<shader effect="model_water"/>
|
||||||
|
<renderquery name="water_tex"/>
|
||||||
|
<renderquery name="sky_cube"/>
|
||||||
|
<renderquery name="sim_time"/>
|
||||||
|
<uniform name="translation" value="0.05 -0.05"/>
|
||||||
|
|
||||||
|
<uniform name="shininess" value="32.0"/>
|
||||||
|
<uniform name="specularStrength" value="1.5"/>
|
||||||
|
<uniform name="waviness" value="0.5"/>
|
||||||
|
<uniform name="waterTint" value="0.2 0.3 0.2"/>
|
||||||
|
<uniform name="murkiness" value="0.6"/>
|
||||||
|
<uniform name="reflectionTint" value="0.3 0.4 0.3"/>
|
||||||
|
<uniform name="reflectionTintStrength" value="0.1"/>
|
||||||
|
</material>
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<material>
|
<material>
|
||||||
<shader effect="model"/>
|
<shader effect="model"/>
|
||||||
<renderquery name="time"/>
|
<renderquery name="sim_time"/>
|
||||||
<define name="USE_WIND" value="1"/>
|
<define name="USE_WIND" value="1"/>
|
||||||
|
<uniform name="windData" value="1.0 1.0"/>
|
||||||
</material>
|
</material>
|
||||||
|
10
binaries/data/mods/public/art/materials/waterfall.xml
Normal file
10
binaries/data/mods/public/art/materials/waterfall.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<material>
|
||||||
|
<shader effect="model_waterfall"/>
|
||||||
|
<alpha_blending/>
|
||||||
|
<renderquery name="sim_time"/>
|
||||||
|
<uniform name="translation" value="0.0 -0.4"/>
|
||||||
|
|
||||||
|
<uniform name="specularPower" value="16.0"/>
|
||||||
|
<uniform name="specularColor" value="1.0 1.0 1.0"/>
|
||||||
|
</material>
|
BIN
binaries/data/mods/public/art/meshes/test/reservoir-water.dae
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/art/meshes/test/reservoir-water.dae
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/art/meshes/test/reservoir.dae
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/art/meshes/test/reservoir.dae
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/art/meshes/test/waterfall.dae
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/art/meshes/test/waterfall.dae
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/art/meshes/test/waterplane.dae
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/art/meshes/test/waterplane.dae
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/art/textures/skins/temp/waterfall.png
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/art/textures/skins/temp/waterfall.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
binaries/data/mods/public/maps/scenarios/reservoir.xml
(Stored with Git LFS)
Normal file
BIN
binaries/data/mods/public/maps/scenarios/reservoir.xml
(Stored with Git LFS)
Normal file
Binary file not shown.
21
binaries/data/mods/public/shaders/effects/model_water.xml
Normal file
21
binaries/data/mods/public/shaders/effects/model_water.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<effect>
|
||||||
|
|
||||||
|
<technique>
|
||||||
|
|
||||||
|
<require shaders="glsl"/>
|
||||||
|
<sort_by_distance/>
|
||||||
|
<pass shader="glsl/model_water">
|
||||||
|
<define name="USE_TRANSPARENT" value="1"/>
|
||||||
|
<define name="USE_SPECULAR" value="1"/>
|
||||||
|
<define name="USE_NORMAL_MAP" value="1"/>
|
||||||
|
<define name="USE_INSTANCING" value="1"/>
|
||||||
|
<define name="REQUIRE_ALPHA_GEQUAL" value="0.05"/>
|
||||||
|
<blend src="src_alpha" dst="one_minus_src_alpha"/>
|
||||||
|
<depth func="less" mask="true"/>
|
||||||
|
</pass>
|
||||||
|
</technique>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</effect>
|
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<effect>
|
||||||
|
|
||||||
|
<technique>
|
||||||
|
|
||||||
|
<require shaders="glsl"/>
|
||||||
|
<sort_by_distance/>
|
||||||
|
<pass shader="glsl/model_waterfall">
|
||||||
|
<define name="USE_TRANSPARENT" value="1"/>
|
||||||
|
<define name="USE_INSTANCING" value="1"/>
|
||||||
|
<blend src="src_alpha" dst="one_minus_src_alpha"/>
|
||||||
|
<depth func="less" mask="false"/>
|
||||||
|
</pass>
|
||||||
|
</technique>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</effect>
|
@ -18,7 +18,7 @@ uniform mat4 instancingTransform;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_WIND
|
#if USE_WIND
|
||||||
uniform vec4 time;
|
uniform vec4 sim_time;
|
||||||
uniform vec4 windData;
|
uniform vec4 windData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -115,9 +115,9 @@ void main()
|
|||||||
|
|
||||||
vec4 cosVec;
|
vec4 cosVec;
|
||||||
// these determine the speed of the wind's "cosine" waves.
|
// these determine the speed of the wind's "cosine" waves.
|
||||||
cosVec.x = time.x * modelPos[0] + position.x;
|
cosVec.x = sim_time.x * modelPos[0] + position.x;
|
||||||
cosVec.y = time.x * modelPos[2] / 3 + instancingTransform[3][0];
|
cosVec.y = sim_time.x * modelPos[2] / 3 + instancingTransform[3][0];
|
||||||
cosVec.z = time.x * abswind / 4 + position.z;
|
cosVec.z = sim_time.x * abswind / 4 + position.z;
|
||||||
|
|
||||||
// calculate "cosines" in parallel, using a smoothed triangle wave
|
// calculate "cosines" in parallel, using a smoothed triangle wave
|
||||||
cosVec = fakeCos(cosVec);
|
cosVec = fakeCos(cosVec);
|
||||||
|
151
binaries/data/mods/public/shaders/glsl/model_water.fs
Normal file
151
binaries/data/mods/public/shaders/glsl/model_water.fs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D baseTex;
|
||||||
|
uniform sampler2D losTex;
|
||||||
|
uniform sampler2D aoTex;
|
||||||
|
uniform sampler2D normTex;
|
||||||
|
uniform sampler2D specTex;
|
||||||
|
|
||||||
|
uniform sampler2D waterTex;
|
||||||
|
uniform samplerCube skyCube;
|
||||||
|
|
||||||
|
#if USE_SHADOW
|
||||||
|
#if USE_SHADOW_SAMPLER
|
||||||
|
uniform sampler2DShadow shadowTex;
|
||||||
|
#if USE_SHADOW_PCF
|
||||||
|
uniform vec4 shadowScale;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
uniform sampler2D shadowTex;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 shininess;
|
||||||
|
uniform float specularStrength;
|
||||||
|
uniform float waviness;
|
||||||
|
uniform vec3 waterTint;
|
||||||
|
uniform float murkiness;
|
||||||
|
uniform vec3 reflectionTint;
|
||||||
|
uniform float reflectionTintStrength;
|
||||||
|
|
||||||
|
|
||||||
|
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 vec4 v_shadow;
|
||||||
|
varying vec2 v_los;
|
||||||
|
|
||||||
|
|
||||||
|
float get_shadow(vec4 coords)
|
||||||
|
{
|
||||||
|
#if USE_SHADOW && !DISABLE_RECEIVE_SHADOWS
|
||||||
|
#if USE_SHADOW_SAMPLER
|
||||||
|
#if USE_SHADOW_PCF
|
||||||
|
vec2 offset = fract(coords.xy - 0.5);
|
||||||
|
vec4 size = vec4(offset + 1.0, 2.0 - offset);
|
||||||
|
vec4 weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (coords.xy - offset).xyxy) * shadowScale.zwzw;
|
||||||
|
return (1.0/9.0)*dot(size.zxzx*size.wwyy,
|
||||||
|
vec4(shadow2D(shadowTex, vec3(weight.zw, coords.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.xw, coords.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.zy, coords.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.xy, coords.z)).r));
|
||||||
|
#else
|
||||||
|
return shadow2D(shadowTex, coords.xyz).r;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (coords.z >= 1.0)
|
||||||
|
return 1.0;
|
||||||
|
return (coords.z <= texture2D(shadowTex, coords.xy).x ? 1.0 : 0.0);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return 1.0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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,
|
||||||
|
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), shininess) * sunColor * specularStrength;
|
||||||
|
|
||||||
|
losMod = texture2D(losTex, v_los).a;
|
||||||
|
|
||||||
|
//losMod = texture2D(losMap, gl_TexCoord[3].st).a;
|
||||||
|
|
||||||
|
#if USE_SHADOW
|
||||||
|
float shadow = get_shadow(vec4(v_shadow.xy - 8*waviness*n.xz, v_shadow.zw));
|
||||||
|
float fresShadow = mix(fresnel, fresnel*shadow, dot(sunColor, vec3(0.16666)));
|
||||||
|
#else
|
||||||
|
float fresShadow = fresnel;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 colour = mix(refrColor + 0.3*specular, reflColor + specular, fresShadow);
|
||||||
|
|
||||||
|
gl_FragColor.rgb = colour * losMod;
|
||||||
|
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
|
74
binaries/data/mods/public/shaders/glsl/model_water.vs
Normal file
74
binaries/data/mods/public/shaders/glsl/model_water.vs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#if USE_GPU_SKINNING
|
||||||
|
// Skinning requires GLSL 1.30 for ivec4 vertex attributes
|
||||||
|
#version 130
|
||||||
|
#else
|
||||||
|
#version 120
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform mat4 transform;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec3 sunDir;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
uniform vec2 losTransform;
|
||||||
|
uniform mat4 shadowTransform;
|
||||||
|
uniform mat4 instancingTransform;
|
||||||
|
|
||||||
|
uniform float sim_time;
|
||||||
|
uniform vec2 translation;
|
||||||
|
|
||||||
|
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
|
||||||
|
uniform vec4 shadowScale;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
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 vec4 v_shadow;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#if USE_SHADOW
|
||||||
|
v_shadow = shadowTransform * worldPos;
|
||||||
|
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
|
||||||
|
v_shadow.xy *= shadowScale.xy;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
v_los = worldPos.xz * losTransform.x + losTransform.y;
|
||||||
|
|
||||||
|
gl_Position = transform * worldPos;
|
||||||
|
}
|
||||||
|
|
20
binaries/data/mods/public/shaders/glsl/model_water.xml
Normal file
20
binaries/data/mods/public/shaders/glsl/model_water.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<program type="glsl">
|
||||||
|
|
||||||
|
<vertex file="glsl/model_water.vs">
|
||||||
|
<stream name="pos"/>
|
||||||
|
<stream name="normal"/>
|
||||||
|
<stream name="uv0"/>
|
||||||
|
<stream name="uv1" if="USE_AO"/>
|
||||||
|
<attrib name="a_vertex" semantics="gl_Vertex"/>
|
||||||
|
<attrib name="a_normal" semantics="gl_Normal"/>
|
||||||
|
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
|
||||||
|
<attrib name="a_uv1" semantics="gl_MultiTexCoord1" if="USE_AO"/>
|
||||||
|
<attrib name="a_skinJoints" semantics="CustomAttribute0" if="USE_GPU_SKINNING"/>
|
||||||
|
<attrib name="a_skinWeights" semantics="CustomAttribute1" if="USE_GPU_SKINNING"/>
|
||||||
|
<attrib name="a_tangent" semantics="CustomAttribute2" if="USE_INSTANCING"/>
|
||||||
|
</vertex>
|
||||||
|
|
||||||
|
<fragment file="glsl/model_water.fs"/>
|
||||||
|
|
||||||
|
</program>
|
82
binaries/data/mods/public/shaders/glsl/model_waterfall.fs
Normal file
82
binaries/data/mods/public/shaders/glsl/model_waterfall.fs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D baseTex;
|
||||||
|
uniform sampler2D losTex;
|
||||||
|
|
||||||
|
|
||||||
|
#if USE_SHADOW
|
||||||
|
#if USE_SHADOW_SAMPLER
|
||||||
|
uniform sampler2DShadow shadowTex;
|
||||||
|
#if USE_SHADOW_PCF
|
||||||
|
uniform vec4 shadowScale;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
uniform sampler2D shadowTex;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 vec4 v_shadow;
|
||||||
|
varying vec2 v_los;
|
||||||
|
varying vec3 v_half;
|
||||||
|
varying vec3 v_normal;
|
||||||
|
|
||||||
|
varying vec3 v_lighting;
|
||||||
|
|
||||||
|
float get_shadow()
|
||||||
|
{
|
||||||
|
#if USE_SHADOW && !DISABLE_RECEIVE_SHADOWS
|
||||||
|
#if USE_SHADOW_SAMPLER
|
||||||
|
#if USE_SHADOW_PCF
|
||||||
|
vec2 offset = fract(v_shadow.xy - 0.5);
|
||||||
|
vec4 size = vec4(offset + 1.0, 2.0 - offset);
|
||||||
|
vec4 weight = (vec4(2.0 - 1.0 / size.xy, 1.0 / size.zw - 1.0) + (v_shadow.xy - offset).xyxy) * shadowScale.zwzw;
|
||||||
|
return (1.0/9.0)*dot(size.zxzx*size.wwyy,
|
||||||
|
vec4(shadow2D(shadowTex, vec3(weight.zw, v_shadow.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.xw, v_shadow.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.zy, v_shadow.z)).r,
|
||||||
|
shadow2D(shadowTex, vec3(weight.xy, v_shadow.z)).r));
|
||||||
|
#else
|
||||||
|
return shadow2D(shadowTex, v_shadow.xyz).r;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (v_shadow.z >= 1.0)
|
||||||
|
return 1.0;
|
||||||
|
return (v_shadow.z <= texture2D(shadowTex, v_shadow.xy).x ? 1.0 : 0.0);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return 1.0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 texdiffuse = textureGrad(baseTex, vec3(fract(v_tex.xy), v_tex.z), dFdx(v_tex.xy), dFdy(v_tex.xy));
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
gl_FragColor.rgb = color;
|
||||||
|
gl_FragColor.a = texdiffuse.a;
|
||||||
|
}
|
||||||
|
|
64
binaries/data/mods/public/shaders/glsl/model_waterfall.vs
Normal file
64
binaries/data/mods/public/shaders/glsl/model_waterfall.vs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#if USE_GPU_SKINNING
|
||||||
|
// Skinning requires GLSL 1.30 for ivec4 vertex attributes
|
||||||
|
#version 130
|
||||||
|
#else
|
||||||
|
#version 120
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform mat4 transform;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec3 sunDir;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
uniform vec2 losTransform;
|
||||||
|
uniform mat4 shadowTransform;
|
||||||
|
uniform mat4 instancingTransform;
|
||||||
|
|
||||||
|
uniform float sim_time;
|
||||||
|
uniform vec2 translation;
|
||||||
|
|
||||||
|
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
|
||||||
|
uniform vec4 shadowScale;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
attribute vec3 a_vertex;
|
||||||
|
attribute vec3 a_normal;
|
||||||
|
attribute vec2 a_uv0;
|
||||||
|
|
||||||
|
|
||||||
|
varying vec4 worldPos;
|
||||||
|
varying vec4 v_tex;
|
||||||
|
varying vec4 v_shadow;
|
||||||
|
varying vec2 v_los;
|
||||||
|
varying vec3 v_half;
|
||||||
|
varying vec3 v_normal;
|
||||||
|
|
||||||
|
varying vec3 v_lighting;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
worldPos = instancingTransform * vec4(a_vertex, 1.0);
|
||||||
|
|
||||||
|
v_tex.xy = a_uv0 + sim_time * translation;
|
||||||
|
|
||||||
|
#if USE_SHADOW
|
||||||
|
v_shadow = shadowTransform * worldPos;
|
||||||
|
#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
|
||||||
|
v_shadow.xy *= shadowScale.xy;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
v_los = worldPos.xz * losTransform.x + losTransform.y;
|
||||||
|
|
||||||
|
vec3 eyeVec = cameraPos.xyz - worldPos.xyz;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
20
binaries/data/mods/public/shaders/glsl/model_waterfall.xml
Normal file
20
binaries/data/mods/public/shaders/glsl/model_waterfall.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<program type="glsl">
|
||||||
|
|
||||||
|
<vertex file="glsl/model_waterfall.vs">
|
||||||
|
<stream name="pos"/>
|
||||||
|
<stream name="normal"/>
|
||||||
|
<stream name="uv0"/>
|
||||||
|
<stream name="uv1" if="USE_AO"/>
|
||||||
|
<attrib name="a_vertex" semantics="gl_Vertex"/>
|
||||||
|
<attrib name="a_normal" semantics="gl_Normal"/>
|
||||||
|
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
|
||||||
|
<attrib name="a_uv1" semantics="gl_MultiTexCoord1" if="USE_AO"/>
|
||||||
|
<attrib name="a_skinJoints" semantics="CustomAttribute0" if="USE_GPU_SKINNING"/>
|
||||||
|
<attrib name="a_skinWeights" semantics="CustomAttribute1" if="USE_GPU_SKINNING"/>
|
||||||
|
<attrib name="a_tangent" semantics="CustomAttribute2" if="USE_INSTANCING"/>
|
||||||
|
</vertex>
|
||||||
|
|
||||||
|
<fragment file="glsl/model_waterfall.fs"/>
|
||||||
|
|
||||||
|
</program>
|
@ -236,10 +236,18 @@ void CShaderUniforms::BindUniforms(const CShaderProgramPtr& shader) const
|
|||||||
|
|
||||||
void CShaderRenderQueries::Add(const char* name)
|
void CShaderRenderQueries::Add(const char* name)
|
||||||
{
|
{
|
||||||
if (name == std::string("time"))
|
if (name == CStr("sim_time"))
|
||||||
{
|
{
|
||||||
m_Items.push_back(std::make_pair(RQUERY_TIME, CStrIntern(name)));
|
m_Items.push_back(std::make_pair(RQUERY_TIME, CStrIntern(name)));
|
||||||
}
|
}
|
||||||
|
else if (name == CStr("water_tex"))
|
||||||
|
{
|
||||||
|
m_Items.push_back(std::make_pair(RQUERY_WATER_TEX, CStrIntern(name)));
|
||||||
|
}
|
||||||
|
else if (name == CStr("sky_cube"))
|
||||||
|
{
|
||||||
|
m_Items.push_back(std::make_pair(RQUERY_SKY_CUBE, CStrIntern(name)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CShaderRenderQueries::GetSize()
|
size_t CShaderRenderQueries::GetSize()
|
||||||
|
@ -170,7 +170,9 @@ public:
|
|||||||
// Add here the types of queries we can make in the renderer
|
// Add here the types of queries we can make in the renderer
|
||||||
enum RENDER_QUERIES
|
enum RENDER_QUERIES
|
||||||
{
|
{
|
||||||
RQUERY_TIME
|
RQUERY_TIME,
|
||||||
|
RQUERY_WATER_TEX,
|
||||||
|
RQUERY_SKY_CUBE
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
#include "renderer/ModelVertexRenderer.h"
|
#include "renderer/ModelVertexRenderer.h"
|
||||||
#include "renderer/Renderer.h"
|
#include "renderer/Renderer.h"
|
||||||
#include "renderer/RenderModifiers.h"
|
#include "renderer/RenderModifiers.h"
|
||||||
|
#include "renderer/SkyManager.h"
|
||||||
|
#include "renderer/WaterManager.h"
|
||||||
|
|
||||||
#include <boost/weak_ptr.hpp>
|
#include <boost/weak_ptr.hpp>
|
||||||
|
|
||||||
@ -705,6 +707,19 @@ void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShade
|
|||||||
shader->Uniform(binding, time, 0,0,0);
|
shader->Uniform(binding, time, 0,0,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (rq.first == RQUERY_WATER_TEX)
|
||||||
|
{
|
||||||
|
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
||||||
|
double time = WaterMgr->m_WaterTexTimer;
|
||||||
|
double period = 1.6;
|
||||||
|
int curTex = (int)(time*60/period) % 60;
|
||||||
|
|
||||||
|
shader->BindTexture("waterTex", WaterMgr->m_NormalMap[curTex]);
|
||||||
|
}
|
||||||
|
else if (rq.first == RQUERY_SKY_CUBE)
|
||||||
|
{
|
||||||
|
shader->BindTexture("skyCube", g_Renderer.GetSkyManager()->GetSkyCube());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier->PrepareModel(shader, model);
|
modifier->PrepareModel(shader, model);
|
||||||
|
@ -67,6 +67,8 @@ SkyManager::SkyManager()
|
|||||||
m_SkySet = L"";
|
m_SkySet = L"";
|
||||||
|
|
||||||
m_HorizonHeight = -150.0f;
|
m_HorizonHeight = -150.0f;
|
||||||
|
|
||||||
|
m_SkyCubeMap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -84,6 +86,77 @@ void SkyManager::LoadSkyTextures()
|
|||||||
texture->Prefetch();
|
texture->Prefetch();
|
||||||
m_SkyTexture[i] = texture;
|
m_SkyTexture[i] = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glGenTextures(1, &m_SkyCubeMap);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, m_SkyCubeMap);
|
||||||
|
|
||||||
|
int types[] = {
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||||
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||||
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||||
|
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
|
||||||
|
};
|
||||||
|
|
||||||
|
const wchar_t* images[numTextures+1] = {
|
||||||
|
L"front",
|
||||||
|
L"back",
|
||||||
|
L"right",
|
||||||
|
L"left",
|
||||||
|
L"top",
|
||||||
|
L"top"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numTextures+1; ++i)
|
||||||
|
{
|
||||||
|
VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i])+L".dds");
|
||||||
|
|
||||||
|
shared_ptr<u8> file;
|
||||||
|
size_t fileSize;
|
||||||
|
g_VFS->LoadFile(path, file, fileSize);
|
||||||
|
|
||||||
|
Tex tex;
|
||||||
|
tex_decode(file, fileSize, &tex);
|
||||||
|
|
||||||
|
tex_transform_to(&tex, (tex.flags | TEX_BOTTOM_UP | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS));
|
||||||
|
|
||||||
|
u8* data = tex_get_data(&tex);
|
||||||
|
|
||||||
|
if (types[i] == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || types[i] == GL_TEXTURE_CUBE_MAP_POSITIVE_Y)
|
||||||
|
{
|
||||||
|
std::vector<u8> rotated(tex.dataSize);
|
||||||
|
|
||||||
|
for (size_t y = 0; y < tex.h; ++y)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < tex.w; ++x)
|
||||||
|
{
|
||||||
|
size_t invx = y, invy = tex.w-x-1;
|
||||||
|
|
||||||
|
rotated[(y*tex.w + x) * 4 + 0] = data[(invy*tex.w + invx) * 4 + 0];
|
||||||
|
rotated[(y*tex.w + x) * 4 + 1] = data[(invy*tex.w + invx) * 4 + 1];
|
||||||
|
rotated[(y*tex.w + x) * 4 + 2] = data[(invy*tex.w + invx) * 4 + 2];
|
||||||
|
rotated[(y*tex.w + x) * 4 + 3] = data[(invy*tex.w + invx) * 4 + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(types[i], 0, GL_RGB, tex.w, tex.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rotated[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glTexImage2D(types[i], 0, GL_RGB, tex.w, tex.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex_free(&tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -93,6 +166,13 @@ void SkyManager::SetSkySet( const CStrW& newSet )
|
|||||||
{
|
{
|
||||||
if(newSet == m_SkySet)
|
if(newSet == m_SkySet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_SkyCubeMap)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_SkyCubeMap);
|
||||||
|
m_SkyCubeMap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
m_SkySet = newSet;
|
m_SkySet = newSet;
|
||||||
|
|
||||||
LoadSkyTextures();
|
LoadSkyTextures();
|
||||||
|
@ -47,6 +47,10 @@ public:
|
|||||||
inline const CStrW& GetSkySet() const {
|
inline const CStrW& GetSkySet() const {
|
||||||
return m_SkySet;
|
return m_SkySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint GetSkyCube() {
|
||||||
|
return m_SkyCubeMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GetSkySet(): Set the sky set name, potentially loading the textures.
|
* GetSkySet(): Set the sky set name, potentially loading the textures.
|
||||||
@ -78,6 +82,8 @@ private:
|
|||||||
|
|
||||||
// Sky textures
|
// Sky textures
|
||||||
CTexturePtr m_SkyTexture[numTextures];
|
CTexturePtr m_SkyTexture[numTextures];
|
||||||
|
|
||||||
|
GLuint m_SkyCubeMap;
|
||||||
|
|
||||||
// Array of image names (defined in SkyManager.cpp), in the order of the IMG_ id's
|
// Array of image names (defined in SkyManager.cpp), in the order of the IMG_ id's
|
||||||
static const wchar_t* s_imageNames[numTextures];
|
static const wchar_t* s_imageNames[numTextures];
|
||||||
|
Loading…
Reference in New Issue
Block a user