mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-12-02 08:31:55 +00:00
de4a7409b2
r4235 | acceptthis | 2013-03-03 19:10:27 +0000 (Sun, 03 Mar 2013) | 5 lines fix missing q2 surface water warp. fix missing q2 underwater warp. tweak altwater shader+rendering to be capable of depth info too. Not enabling that yet. fix q2 conchar colour issue. fix rtlights in water. attempt to remove borders of shadowmap lights. implement support for dynamic resolution shadowmaps. still needs to choose the resolution properly. ------------------------------------------------------------------------ git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4231 fc73d0e0-1445-4013-8a0c-d673dee63da5
277 lines
7.7 KiB
GLSL
277 lines
7.7 KiB
GLSL
!!permu BUMP
|
|
!!permu SKELETAL
|
|
!!permu UPPERLOWER
|
|
!!permu FOG
|
|
!!cvarf r_glsl_offsetmapping_scale
|
|
|
|
//this is the main shader responsible for realtime dlights.
|
|
|
|
//texture units:
|
|
//s0=diffuse, s1=normal, s2=specular, s3=shadowmap
|
|
//custom modifiers:
|
|
//PCF(shadowmap)
|
|
//CUBEPROJ(projected cubemap)
|
|
//SPOT(projected circle
|
|
//CUBESHADOW
|
|
|
|
#if 0 && defined(GL_ARB_texture_gather) && defined(PCF)
|
|
#extension GL_ARB_texture_gather : enable
|
|
#endif
|
|
|
|
#ifdef UPPERLOWER
|
|
#define UPPER
|
|
#define LOWER
|
|
#endif
|
|
|
|
|
|
varying vec2 tcbase;
|
|
varying vec3 lightvector;
|
|
#if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
varying vec3 eyevector;
|
|
#endif
|
|
|
|
#if defined(PCF) || defined(CUBEPROJ) || defined(SPOT)
|
|
varying vec4 vtexprojcoord;
|
|
uniform mat4 l_cubematrix;
|
|
#ifndef SPOT
|
|
uniform mat4 l_projmatrix;
|
|
#endif
|
|
#endif
|
|
#ifdef VERTEX_SHADER
|
|
#include "sys/skeletal.h"
|
|
uniform vec3 l_lightposition;
|
|
attribute vec2 v_texcoord;
|
|
#if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
uniform vec3 e_eyepos;
|
|
#endif
|
|
void main ()
|
|
{
|
|
vec3 n, s, t, w;
|
|
gl_Position = skeletaltransform_wnst(w,n,s,t);
|
|
tcbase = v_texcoord; //pass the texture coords straight through
|
|
vec3 lightminusvertex = l_lightposition - w.xyz;
|
|
lightvector.x = -dot(lightminusvertex, s.xyz);
|
|
lightvector.y = dot(lightminusvertex, t.xyz);
|
|
lightvector.z = dot(lightminusvertex, n.xyz);
|
|
#if defined(SPECULAR)||defined(OFFSETMAPPING)
|
|
vec3 eyeminusvertex = e_eyepos - w.xyz;
|
|
eyevector.x = -dot(eyeminusvertex, s.xyz);
|
|
eyevector.y = dot(eyeminusvertex, t.xyz);
|
|
eyevector.z = dot(eyeminusvertex, n.xyz);
|
|
#endif
|
|
#if defined(PCF) || defined(SPOT) || defined(PROJECTION)
|
|
//for texture projections/shadowmapping on dlights
|
|
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef FRAGMENT_SHADER
|
|
#include "sys/fog.h"
|
|
uniform sampler2D s_t0; //diffuse
|
|
|
|
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
uniform sampler2D s_t1; //normalmap
|
|
#endif
|
|
#ifdef SPECULAR
|
|
uniform sampler2D s_t2; //specular
|
|
#endif
|
|
#ifdef CUBEPROJ
|
|
uniform samplerCube s_t3; //projected cubemap
|
|
#endif
|
|
#ifdef PCF
|
|
#ifdef CUBESHADOW
|
|
uniform samplerCubeShadow s_t4; //shadowmap
|
|
#else
|
|
#if 0//def GL_ARB_texture_gather
|
|
uniform sampler2D s_t4;
|
|
#else
|
|
uniform sampler2DShadow s_t4;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#ifdef LOWER
|
|
uniform sampler2D s_t5; //pants colours
|
|
uniform vec3 e_lowercolour;
|
|
#endif
|
|
#ifdef UPPER
|
|
uniform sampler2D s_t6; //shirt colours
|
|
uniform vec3 e_uppercolour;
|
|
#endif
|
|
|
|
|
|
uniform float l_lightradius;
|
|
uniform vec3 l_lightcolour;
|
|
uniform vec3 l_lightcolourscale;
|
|
#ifdef PCF
|
|
uniform vec4 l_shadowmapinfo; //xy are the texture scale, z is 1, w is the scale.
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef PCF
|
|
//#define shadow2DProj(t,c) (vec2(1.0,1.0))
|
|
//#define shadow2DProj(t,c) texture2DProj(t,c).rg
|
|
|
|
float ShadowmapFilter(void)
|
|
{
|
|
//dehomogonize input
|
|
vec3 shadowcoord = (vtexprojcoord.xyz / vtexprojcoord.w);
|
|
|
|
#ifdef CUBESHADOW
|
|
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
|
|
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
|
|
#else
|
|
|
|
#ifdef SPOT
|
|
//bias it. don't bother figuring out which side or anything, its not needed
|
|
//l_projmatrix contains the light's projection matrix so no other magic needed
|
|
shadowcoord.xyz = (shadowcoord.xyz + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);
|
|
#else
|
|
//figure out which axis to use
|
|
//texture is arranged thusly:
|
|
//forward left up
|
|
//back right down
|
|
vec3 dir = abs(shadowcoord);
|
|
//assume z is the major axis (ie: forward from the light)
|
|
vec3 t = shadowcoord;
|
|
float ma = dir.z;
|
|
vec3 axis = vec3(1.0, 1.0, 1.0);
|
|
if (dir.x > ma)
|
|
{
|
|
ma = dir.x;
|
|
t = shadowcoord.zyx;
|
|
axis.x = 3.0;
|
|
}
|
|
if (dir.y > ma)
|
|
{
|
|
ma = dir.y;
|
|
t = shadowcoord.xzy;
|
|
axis.x = 5.0;
|
|
}
|
|
if (t.z > 0.0)
|
|
{
|
|
axis.y = 3.0;
|
|
t.z = -t.z;
|
|
}
|
|
|
|
|
|
//we also need to pass the result through the light's projection matrix too
|
|
vec4 nsc =l_projmatrix*vec4(t, 1.0);
|
|
shadowcoord = (nsc.xyz / nsc.w);
|
|
|
|
//scale to match the light's precision and pinch inwards, so we never sample over the edge
|
|
shadowcoord.st *= l_shadowmapinfo.w * (1.0-l_shadowmapinfo.st);
|
|
|
|
//now bias and relocate it
|
|
shadowcoord = (shadowcoord + axis.xyz) * vec3(0.5/3.0, 0.5/2.0, 0.5);
|
|
#endif
|
|
|
|
#if 0//def GL_ARB_texture_gather
|
|
vec2 ipart, fpart;
|
|
#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))
|
|
vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));
|
|
vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));
|
|
vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));
|
|
vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));
|
|
//we now have 4*4 results, woo
|
|
//we can just average them for 1/16th precision, but that's still limited graduations
|
|
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
|
|
vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength
|
|
mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows
|
|
return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.
|
|
|
|
#else
|
|
#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapinfo.xyz)).r
|
|
float s = 0.0;
|
|
s += dosamp(-1.0, -1.0);
|
|
s += dosamp(-1.0, 0.0);
|
|
s += dosamp(-1.0, 1.0);
|
|
s += dosamp(0.0, -1.0);
|
|
s += dosamp(0.0, 0.0);
|
|
s += dosamp(0.0, 1.0);
|
|
s += dosamp(1.0, -1.0);
|
|
s += dosamp(1.0, 0.0);
|
|
s += dosamp(1.0, 1.0);
|
|
return s/9.0;
|
|
#endif
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef OFFSETMAPPING
|
|
#include "sys/offsetmapping.h"
|
|
#endif
|
|
void main ()
|
|
{
|
|
//read raw texture samples (offsetmapping munges the tex coords first)
|
|
#ifdef OFFSETMAPPING
|
|
vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);
|
|
#define tcbase tcoffsetmap
|
|
#endif
|
|
vec3 bases = vec3(texture2D(s_t0, tcbase));
|
|
#ifdef UPPER
|
|
vec4 uc = texture2D(s_t6, tcbase);
|
|
bases.rgb += uc.rgb*e_uppercolour*uc.a;
|
|
#endif
|
|
#ifdef LOWER
|
|
vec4 lc = texture2D(s_t5, tcbase);
|
|
bases.rgb += lc.rgb*e_lowercolour*lc.a;
|
|
#endif
|
|
#if defined(BUMP) || defined(SPECULAR)
|
|
vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);
|
|
#endif
|
|
#ifdef SPECULAR
|
|
vec4 specs = texture2D(s_t2, tcbase);
|
|
#endif
|
|
|
|
vec3 nl = normalize(lightvector);
|
|
float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);
|
|
vec3 diff;
|
|
#ifdef BUMP
|
|
diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
|
|
#else
|
|
//we still do bumpmapping even without bumps to ensure colours are always sane. light.exe does it too.
|
|
diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));
|
|
#endif
|
|
|
|
|
|
#ifdef SPECULAR
|
|
vec3 halfdir = normalize(normalize(eyevector) + nl);
|
|
float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);
|
|
diff += l_lightcolourscale.z * spec * specs.rgb;
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CUBEPROJ
|
|
/*filter the colour by the cubemap projection*/
|
|
diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;
|
|
#endif
|
|
|
|
#if defined(SPOT)
|
|
/*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/
|
|
if (vtexprojcoord.w < 0.0) discard;
|
|
vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));
|
|
#endif
|
|
|
|
#ifdef PCF
|
|
/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
|
|
//diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
|
|
colorscale *= ShadowmapFilter();
|
|
// gl_FragColor.rgb = vec3(ShadowmapFilter());
|
|
|
|
#endif
|
|
|
|
#if defined(PROJECTION)
|
|
/*2d projection, not used*/
|
|
// diff *= texture2d(s_t3, shadowcoord);
|
|
#endif
|
|
|
|
gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);
|
|
}
|
|
#endif
|