forked from 0ad/0ad
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"/>
|
||||
<alpha_blending/>
|
||||
<define name="USE_TRANSPARENT" value="1"/>
|
||||
<renderquery name="time"/>
|
||||
<renderquery name="sim_time"/>
|
||||
<define name="USE_WIND" value="1"/>
|
||||
<uniform name="windData" value="1.0 1.0"/>
|
||||
</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"?>
|
||||
<material>
|
||||
<shader effect="model"/>
|
||||
<renderquery name="time"/>
|
||||
<renderquery name="sim_time"/>
|
||||
<define name="USE_WIND" value="1"/>
|
||||
<uniform name="windData" value="1.0 1.0"/>
|
||||
</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
|
||||
|
||||
#if USE_WIND
|
||||
uniform vec4 time;
|
||||
uniform vec4 sim_time;
|
||||
uniform vec4 windData;
|
||||
#endif
|
||||
|
||||
@ -115,9 +115,9 @@ void main()
|
||||
|
||||
vec4 cosVec;
|
||||
// these determine the speed of the wind's "cosine" waves.
|
||||
cosVec.x = time.x * modelPos[0] + position.x;
|
||||
cosVec.y = time.x * modelPos[2] / 3 + instancingTransform[3][0];
|
||||
cosVec.z = time.x * abswind / 4 + position.z;
|
||||
cosVec.x = sim_time.x * modelPos[0] + position.x;
|
||||
cosVec.y = sim_time.x * modelPos[2] / 3 + instancingTransform[3][0];
|
||||
cosVec.z = sim_time.x * abswind / 4 + position.z;
|
||||
|
||||
// calculate "cosines" in parallel, using a smoothed triangle wave
|
||||
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)
|
||||
{
|
||||
if (name == std::string("time"))
|
||||
if (name == CStr("sim_time"))
|
||||
{
|
||||
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()
|
||||
|
@ -170,7 +170,9 @@ public:
|
||||
// Add here the types of queries we can make in the renderer
|
||||
enum RENDER_QUERIES
|
||||
{
|
||||
RQUERY_TIME
|
||||
RQUERY_TIME,
|
||||
RQUERY_WATER_TEX,
|
||||
RQUERY_SKY_CUBE
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "renderer/ModelVertexRenderer.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/SkyManager.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
@ -705,6 +707,19 @@ void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShade
|
||||
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);
|
||||
|
@ -67,6 +67,8 @@ SkyManager::SkyManager()
|
||||
m_SkySet = L"";
|
||||
|
||||
m_HorizonHeight = -150.0f;
|
||||
|
||||
m_SkyCubeMap = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -84,6 +86,77 @@ void SkyManager::LoadSkyTextures()
|
||||
texture->Prefetch();
|
||||
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)
|
||||
return;
|
||||
|
||||
if (m_SkyCubeMap)
|
||||
{
|
||||
glDeleteTextures(1, &m_SkyCubeMap);
|
||||
m_SkyCubeMap = 0;
|
||||
}
|
||||
|
||||
m_SkySet = newSet;
|
||||
|
||||
LoadSkyTextures();
|
||||
|
@ -47,6 +47,10 @@ public:
|
||||
inline const CStrW& GetSkySet() const {
|
||||
return m_SkySet;
|
||||
}
|
||||
|
||||
GLuint GetSkyCube() {
|
||||
return m_SkyCubeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetSkySet(): Set the sky set name, potentially loading the textures.
|
||||
@ -78,6 +82,8 @@ private:
|
||||
|
||||
// Sky textures
|
||||
CTexturePtr m_SkyTexture[numTextures];
|
||||
|
||||
GLuint m_SkyCubeMap;
|
||||
|
||||
// Array of image names (defined in SkyManager.cpp), in the order of the IMG_ id's
|
||||
static const wchar_t* s_imageNames[numTextures];
|
||||
|
Loading…
Reference in New Issue
Block a user