fteqw/engine/shaders/glsl/lpp_light.glsl

75 lines
2.2 KiB
GLSL

//this shader is a light shader. ideally drawn with a quad covering the entire region
//the output is contribution from this light (which will be additively blended)
//you can blame Electro for much of the maths in here.
!!ver 100 450
//FIXME: !!permu FOG
!!samps shadowmap 2
#define USE_ARB_SHADOW
#include "sys/defs.h"
#include "sys/pcf.h"
//s_t0 is the depth
//s_t1 is the normals+spec-exponent
//output should be amount of light hitting the surface.
varying vec4 tf;
#ifdef VERTEX_SHADER
void main()
{
tf = ftetransform();
gl_Position = tf;
}
#endif
#ifdef FRAGMENT_SHADER
#define out_diff fte_fragdata0
#define out_spec fte_fragdata1
vec3 calcLightWorldPos(vec2 screenPos, float depth)
{
vec4 pos = m_invviewprojection * vec4(screenPos.xy, (depth*2.0)-1.0, 1.0);
return pos.xyz / pos.w;
}
void main ()
{
vec3 lightColour = l_lightcolour.rgb;
vec2 fc = tf.xy / tf.w;
vec2 gc = (1.0 + fc) / 2.0;
float depth = texture2D(s_t0, gc).r;
vec4 data = texture2D(s_t1, gc);
vec3 norm = data.xyz;
float spec_exponent = data.a;
/* calc where the wall that generated this sample came from */
vec3 worldPos = calcLightWorldPos(fc, depth);
/*we need to know the cube projection (for both cubemaps+shadows)*/
vec4 cubeaxis = l_cubematrix*vec4(worldPos.xyz, 1.0);
/*calc ambient lighting term*/
vec3 lightDir = l_lightposition - worldPos;
float atten = max(1.0 - (dot(lightDir, lightDir)/(l_lightradius*l_lightradius)), 0.0);
/*calc diffuse lighting term*/
lightDir = normalize(lightDir);
float nDotL = dot(norm, lightDir);
float lightDiffuse = max(0.0, nDotL);
/*calc specular lighting term*/
vec3 halfdir = normalize(normalize(e_eyepos - worldPos) + lightDir); //ASSUMPTION: e_eyepos requires an identity modelmatrix (true for world+sprites, but usually not for models/bsps)
float spec = pow(max(dot(halfdir, norm), 0.0), spec_exponent);
//fixme: apply fog?
//fixme: cubemap filters
float shadows = ShadowmapFilter(s_shadowmap, cubeaxis);
lightColour *= atten;
out_diff = vec4(lightColour * (l_lightcolourscale.x + l_lightcolourscale.y*lightDiffuse*shadows), 1.0);
out_spec = vec4(lightColour * l_lightcolourscale.z*spec*shadows, 1.0);
}
#endif