a85f3c5c71
make sure demos freeze at the start, instead of reading everything out of the file while we're still loading content. added a couple of lame 'list' commands. added 'in' command. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4928 fc73d0e0-1445-4013-8a0c-d673dee63da5
2710 lines
72 KiB
C
2710 lines
72 KiB
C
/*
|
|
WARNING: THIS FILE IS GENERATED BY 'generatebuiltinsl.c'.
|
|
YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|
*/
|
|
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "altwater",
|
|
"!!cvarf r_glsl_turbscale\n"
|
|
//modifier: REFLECT (s_t2 is a reflection instead of diffusemap)
|
|
//modifier: STRENGTH (0.1 = fairly gentle, 0.2 = big waves)
|
|
//modifier: FRESNEL (5=water)
|
|
//modifier: TXSCALE (0.2 - wave strength)
|
|
//modifier: RIPPLEMAP (s_t3 contains a ripplemap
|
|
//modifier: TINT (some colour value)
|
|
|
|
"#ifndef FRESNEL\n"
|
|
"#define FRESNEL 5.0\n"
|
|
"#endif\n"
|
|
"#ifndef STRENGTH\n"
|
|
"#define STRENGTH 0.1\n"
|
|
"#endif\n"
|
|
"#ifndef TXSCALE\n"
|
|
"#define TXSCALE 0.2\n"
|
|
"#endif\n"
|
|
"#ifndef TINT\n"
|
|
"#define TINT vec3(0.7, 0.8, 0.7)\n"
|
|
"#endif\n"
|
|
"#ifndef FOGTINT\n"
|
|
"#define FOGTINT vec3(0.2, 0.3, 0.2)\n"
|
|
"#endif\n"
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 tf;\n"
|
|
"varying vec3 norm;\n"
|
|
"varying vec3 eye;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec3 v_normal;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"tc = v_texcoord.st;\n"
|
|
"tf = ftetransform();\n"
|
|
"norm = v_normal;\n"
|
|
"eye = e_eyepos - v_position.xyz;\n"
|
|
"gl_Position = tf;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#define s_refract s_t0\n"
|
|
"#define s_reflect s_t1\n"
|
|
"#define s_ripplemap s_t2\n"
|
|
"#define s_refractdepth s_t3\n"
|
|
|
|
"uniform float cvar_r_glsl_turbscale;\n"
|
|
"uniform sampler2D s_normalmap;\n"
|
|
"uniform sampler2D s_diffuse;\n"
|
|
"uniform sampler2D s_refract; //refract\n"
|
|
"uniform sampler2D s_reflect; //reflection\n"
|
|
"uniform sampler2D s_refractdepth; //refraction depth\n"
|
|
"uniform sampler2D s_ripplemap; //ripplemap\n"
|
|
|
|
"uniform float e_time;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"vec2 stc, ntc;\n"
|
|
"vec3 n, refr, refl;\n"
|
|
"float fres;\n"
|
|
"float depth;\n"
|
|
"stc = (1.0 + (tf.xy / tf.w)) * 0.5;\n"
|
|
//hack the texture coords slightly so that there are no obvious gaps
|
|
"stc.t -= 1.5*norm.z/1080.0;\n"
|
|
|
|
//apply q1-style warp, just for kicks
|
|
"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
|
|
"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
|
|
|
|
//generate the two wave patterns from the normalmap
|
|
"n = (texture2D(s_normalmap, TXSCALE*tc + vec2(e_time*0.1, 0.0)).xyz);\n"
|
|
"n += (texture2D(s_normalmap, TXSCALE*tc - vec2(0, e_time*0.097)).xyz);\n"
|
|
"n -= 1.0 - 4.0/256.0;\n"
|
|
|
|
"#ifdef RIPPLEMAP\n"
|
|
"n += texture2D(s_ripplemap, stc).rgb*3.0;\n"
|
|
"#endif\n"
|
|
|
|
//the fresnel term decides how transparent the water should be
|
|
"fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n"
|
|
|
|
"#ifdef DEPTH\n"
|
|
"float far = #include \"cvar/gl_maxdist\";\n"
|
|
"float near = #include \"cvar/gl_mindist\";\n"
|
|
//get depth value at the surface
|
|
"float sdepth = gl_FragCoord.z;\n"
|
|
"sdepth = (2.0*near) / (far + near - sdepth * (far - near));\n"
|
|
"sdepth = mix(near, far, sdepth);\n"
|
|
|
|
//get depth value at the ground beyond the surface.
|
|
"float gdepth = texture2D(s_refractdepth, stc).x;\n"
|
|
"gdepth = (2.0*near) / (far + near - gdepth * (far - near));\n"
|
|
"if (gdepth >= 0.5)\n"
|
|
"{\n"
|
|
"gdepth = sdepth;\n"
|
|
"depth = 0.0;\n"
|
|
"}\n"
|
|
"else\n"
|
|
"{\n"
|
|
"gdepth = mix(near, far, gdepth);\n"
|
|
"depth = gdepth - sdepth;\n"
|
|
"}\n"
|
|
|
|
//reduce the normals in shallow water (near walls, reduces the pain of linear sampling)
|
|
"if (depth < 100.0)\n"
|
|
"n *= depth/100.0;\n"
|
|
"#else\n"
|
|
"depth = 1.0;\n"
|
|
"#endif \n"
|
|
|
|
|
|
//refraction image (and water fog, if possible)
|
|
"refr = texture2D(s_refract, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT;\n"
|
|
"#ifdef DEPTH\n"
|
|
"refr = mix(refr, FOGTINT, min(depth/4096.0, 1.0));\n"
|
|
"#endif\n"
|
|
|
|
//reflection/diffuse
|
|
"#ifdef REFLECT\n"
|
|
"refl = texture2D(s_reflect, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb;\n"
|
|
"#else\n"
|
|
"refl = texture2D(s_diffuse, ntc).xyz;\n"
|
|
"#endif\n"
|
|
//FIXME: add specular
|
|
|
|
//interplate by fresnel
|
|
"refr = mix(refr, refl, fres);\n"
|
|
|
|
//done
|
|
"gl_FragColor = vec4(refr, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_blur",
|
|
//apply gaussian filter
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
/*offset should be 1.2 pixels away from the center*/
|
|
"uniform vec3 e_glowmod;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor =\n"
|
|
"0.3125 * texture2D(s_t0, tc - e_glowmod.st) +\n"
|
|
"0.375 * texture2D(s_t0, tc) +\n"
|
|
"0.3125 * texture2D(s_t0, tc + e_glowmod.st);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_filter",
|
|
"!!cvarv r_bloom_filter\n"
|
|
//the bloom filter
|
|
//filter out any texels which are not to bloom
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform vec3 cvar_r_bloom_filter;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_final",
|
|
"!!cvarf r_bloom\n"
|
|
//add them together
|
|
//optionally apply tonemapping
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"uniform sampler2D s_t2;\n"
|
|
"uniform sampler2D s_t3;\n"
|
|
"uniform float cvar_r_bloom;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = \n"
|
|
"texture2D(s_t0, tc) +\n"
|
|
"cvar_r_bloom*(\n"
|
|
"texture2D(s_t1, tc) +\n"
|
|
"texture2D(s_t2, tc) +\n"
|
|
"texture2D(s_t3, tc)\n"
|
|
") ;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "colourtint",
|
|
//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example)
|
|
"varying vec4 tf;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = tf = vec4(v_position.xy,-1.0, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler3D s_t1;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec2 fc;\n"
|
|
"fc = tf.xy / tf.w;\n"
|
|
"vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb;\n"
|
|
"#define LUTSIZE 16.0\n"
|
|
"vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE);\n"
|
|
"vec3 bias = vec3(1.0/(2.0*LUTSIZE));\n"
|
|
"gl_FragColor = texture3D(s_t1, raw * scale + bias);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_opaque",
|
|
//opaque surfaces are drawn to the render target to mask out skies
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_rays",
|
|
"!!cvarf crep_decay\n"
|
|
"!!cvarf crep_density\n"
|
|
"!!cvarf crep_weight\n"
|
|
|
|
//this is a post-processing shader, drawn in 2d
|
|
//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky)
|
|
//this shader then just smudges the sky out a bit as though its coming from the sun or whatever through the clouds.
|
|
//yoinked from http://fabiensanglard.net/lightScattering/index.php
|
|
|
|
"varying vec2 tc;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = vec4(v_position, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"const float crep_decay = 0.94;\n"
|
|
"const float crep_density = 0.5;\n"
|
|
"const float crep_weight = 0.2;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform vec3 l_lightscreen;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"const int NUM_SAMPLES = 100;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec2 deltaTextCoord = vec2(tc.st - l_lightscreen.xy);\n"
|
|
"vec2 textCoo = tc.st;\n"
|
|
"deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density;\n"
|
|
"float illuminationDecay = 1.0;\n"
|
|
"gl_FragColor = vec4(0.0,0.0,0.0,0.0);\n"
|
|
"for(int i=0; i < NUM_SAMPLES ; i++)\n"
|
|
"{\n"
|
|
"textCoo -= deltaTextCoord;\n"
|
|
"vec4 sample = texture2D(s_t0, textCoo);\n"
|
|
"sample *= illuminationDecay * crep_weight;\n"
|
|
"gl_FragColor += sample;\n"
|
|
"illuminationDecay *= crep_decay;\n"
|
|
"}\n"
|
|
"gl_FragColor *= vec4(l_lightcolour, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_sky",
|
|
//pretty much a regular sky shader
|
|
//though in reality we should render a sun circle in the middle.
|
|
//still, its kinda cool to have scrolling clouds masking out parts of the sun.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"varying vec3 pos;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"pos = v_position.xyz;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform float e_time;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"varying vec3 pos;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 tccoord;\n"
|
|
"vec3 dir = pos - e_eyepos;\n"
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"vec4 clouds = texture2D(s_t1, tccoord);\n"
|
|
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "depthonly",
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
|
|
//standard shader used for drawing shadowmap depth.
|
|
//also used for masking off portals and other things that want depth and no colour.
|
|
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
|
//the vertex shader is responsible for calculating lighting values.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = skeletaltransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
//must always draw something, supposedly. It might as well be black.
|
|
"gl_FragColor = vec4(0, 0, 0, 1);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "depthonly",
|
|
//used for generating shadowmaps and stuff that draws nothing.
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float3 col: TEXCOORD;\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.col = inp.pos.xyz - l_lightposition;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#if LEVEL < 0x10000\n"
|
|
//pre dx10 requires that we ALWAYS write to a target.
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return float4(0, 0, 0, 1);\n"
|
|
"}\n"
|
|
"#else\n"
|
|
//but on 10, it'll write depth automatically and we don't care about colour.
|
|
"void main (v2f inp)\n"
|
|
"{\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "default2d",
|
|
//this shader is present for support for gles/gl3core contexts
|
|
//it is single-texture-with-vertex-colours, and doesn't do anything special.
|
|
//beware that a few things use this, including apparently fonts and bloom rescaling.
|
|
//its really not meant to do anything special.
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec4 f = vc;\n"
|
|
"#ifdef PREMUL\n"
|
|
"f.rgb *= f.a;\n"
|
|
"#endif\n"
|
|
"f *= texture2D(s_t0, tc);\n"
|
|
"gl_FragColor = f;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "default2d",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_projection, inp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_t0;\n"
|
|
"SamplerState s_t0;\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return t_t0.Sample(s_t0, inp.tc) * inp.vcol;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultadditivesprite",
|
|
"!!permu FOG\n"
|
|
|
|
//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing.
|
|
//includes fog, apparently.
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"uniform vec4 e_colourident;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultskin",
|
|
"!!permu FULLBRIGHT\n"
|
|
"!!permu UPPERLOWER\n"
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
"!!permu FOG\n"
|
|
"!!permu BUMP\n"
|
|
"!!cvarf r_glsl_offsetmapping_scale\n"
|
|
"!!cvarf gl_specular\n"
|
|
|
|
"#include \"sys/defs.h\"\n"
|
|
|
|
//standard shader used for models.
|
|
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
|
//the vertex shader is responsible for calculating lighting values.
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec3 light;\n"
|
|
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
|
|
"varying vec3 eyevector;\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n"
|
|
"vec3 n, s, t, w;\n"
|
|
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
|
|
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
|
|
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
|
|
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
|
|
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
|
|
"#else\n"
|
|
"vec3 n;\n"
|
|
"gl_Position = skeletaltransform_n(n);\n"
|
|
"#endif\n"
|
|
|
|
"float d = dot(n,e_light_dir);\n"
|
|
"if (d < 0.0) //vertex shader. this might get ugly, but I don't really want to make it per vertex.\n"
|
|
"d = 0.0; //this avoids the dark side going below the ambient level.\n"
|
|
"light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
|
|
"tc = v_texcoord;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#include \"sys/fog.h\"\n"
|
|
|
|
"#if defined(SPECULAR)\n"
|
|
"uniform float cvar_gl_specular;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"#include \"sys/offsetmapping.h\"\n"
|
|
"#endif\n"
|
|
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec4 col, sp;\n"
|
|
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);\n"
|
|
"#define tc tcoffsetmap\n"
|
|
"#endif\n"
|
|
|
|
"col = texture2D(s_diffuse, tc);\n"
|
|
"#ifdef UPPER\n"
|
|
"vec4 uc = texture2D(s_upper, tc);\n"
|
|
"col.rgb += uc.rgb*e_uppercolour*uc.a;\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"vec4 lc = texture2D(s_lower, tc);\n"
|
|
"col.rgb += lc.rgb*e_lowercolour*lc.a;\n"
|
|
"#endif\n"
|
|
|
|
"#if defined(BUMP) && defined(SPECULAR)\n"
|
|
"vec3 bumps = normalize(vec3(texture2D(s_normalmap, tc)) - 0.5);\n"
|
|
"vec4 specs = texture2D(s_specular, tc);\n"
|
|
|
|
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0));\n"
|
|
"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n"
|
|
"col.rgb += cvar_gl_specular * spec * specs.rgb;\n"
|
|
"#endif\n"
|
|
|
|
"col.rgb *= light;\n"
|
|
|
|
"#ifdef FULLBRIGHT\n"
|
|
"vec4 fb = texture2D(s_fullbright, tc);\n"
|
|
// col.rgb = mix(col.rgb, fb.rgb, fb.a);
|
|
"col.rgb += fb.rgb * fb.a;\n"
|
|
"#endif\n"
|
|
|
|
"gl_FragColor = fog4(col * e_colourident);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultskin",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float3 normal: NORMAL;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float3 light: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
//attribute vec2 v_texcoord;
|
|
//uniform vec3 e_light_dir;
|
|
//uniform vec3 e_light_mul;
|
|
//uniform vec3 e_light_ambient;
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.light = e_light_ambient + (dot(inp.normal,e_light_dir)*e_light_mul);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_diffuse : register(t0);\n"
|
|
"#ifdef UPPER\n"
|
|
"Texture2D t_upper : register(t1);\n"
|
|
"Texture2D t_lower : register(t2);\n"
|
|
"Texture2D t_fullbright : register(t3);\n"
|
|
"#else\n"
|
|
"Texture2D t_fullbright : register(t1);\n"
|
|
"#endif\n"
|
|
|
|
"SamplerState SampleType;\n"
|
|
|
|
//uniform vec4 e_colourident;
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 col;\n"
|
|
"col = t_diffuse.Sample(SampleType, inp.tc);\n"
|
|
|
|
"#ifdef MASK\n"
|
|
"#ifndef MASKOP\n"
|
|
"#define MASKOP >= //drawn if (alpha OP ref) is true.\n"
|
|
"#endif\n"
|
|
//support for alpha masking
|
|
"if (!(col.a MASKOP MASK))\n"
|
|
"discard;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef UPPER\n"
|
|
"float4 uc = t_upper.Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = lerp(col.rgb, uc.rgb*e_uppercolour, uc.a);\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"float4 lc = t_lower.Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = lerp(col.rgb, lc.rgb*e_lowercolour, lc.a);\n"
|
|
"#endif\n"
|
|
"col.rgb *= inp.light;\n"
|
|
//#ifdef FULLBRIGHT
|
|
"float4 fb = t_fullbright.Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = lerp(col.rgb, fb.rgb, fb.a);\n"
|
|
//#endif
|
|
"return col;\n"
|
|
// return fog4(col * e_colourident);
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultsky",
|
|
//regular sky shader for scrolling q1 skies
|
|
//the sky surfaces are thrown through this as-is.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"varying vec3 pos;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"pos = v_position.xyz;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform float e_time;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"varying vec3 pos;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 tccoord;\n"
|
|
"vec3 dir = pos - e_eyepos;\n"
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"vec4 clouds = texture2D(s_t1, tccoord);\n"
|
|
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D9QUAKE
|
|
{QR_DIRECT3D9, 9, "defaultsky",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"#ifndef FRAGMENT_SHADER\n"
|
|
"float4 pos: POSITION;\n"
|
|
"#endif\n"
|
|
"float3 vpos: TEXCOORD0;\n"
|
|
"};\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"float4x4 m_modelviewprojection;\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
|
|
"outp.vpos = inp.pos;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"float e_time;\n"
|
|
"float3 e_eyepos;\n"
|
|
|
|
"float l_lightradius;\n"
|
|
"float3 l_lightcolour;\n"
|
|
"float3 l_lightposition;\n"
|
|
|
|
"sampler s_diffuse; /*diffuse*/\n"
|
|
"sampler s_fullbright; /*normal*/\n"
|
|
"float4 main (v2f inp) : COLOR0\n"
|
|
"{\n"
|
|
"float2 tccoord;\n"
|
|
|
|
"float3 dir = inp.vpos - e_eyepos;\n"
|
|
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"float4 solid = tex2D(s_diffuse, tccoord);\n"
|
|
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"float4 clouds = tex2D(s_fullbright, tccoord);\n"
|
|
|
|
"return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultsky",
|
|
//regular sky shader for scrolling q1 skies
|
|
//the sky surfaces are thrown through this as-is.
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float3 mpos: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.mpos = outp.pos.xyz;\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_diffuse : register(t0);\n"
|
|
"Texture2D t_fullbright : register(t1);\n"
|
|
"SamplerState s_diffuse : register(s0);\n"
|
|
"SamplerState s_fullbright : register(s1);\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float2 tccoord;\n"
|
|
"float3 dir = inp.mpos - v_eyepos;\n"
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"float4 solid = t_diffuse.Sample(s_diffuse, tccoord);\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"float4 clouds = t_fullbright.Sample(s_fullbright, tccoord);\n"
|
|
"return lerp(solid, clouds, clouds.a);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultfill",
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"varying vec4 vc;\n"
|
|
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"varying vec4 vc;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = vc;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultfill",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_projection, inp.pos);\n"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return inp.vcol;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultsprite",
|
|
"!!permu FOG\n"
|
|
//used by both particles and sprites.
|
|
//note the fog blending mode is all that differs from defaultadditivesprite
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"uniform vec4 e_colourident;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec4 col = texture2D(s_t0, tc);\n"
|
|
"#ifdef MASK\n"
|
|
"if (col.a < float(MASK))\n"
|
|
"discard;\n"
|
|
"#endif\n"
|
|
"gl_FragColor = fog4blend(col * vc * e_colourident);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultsprite",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_diffuse : register(t0);\n"
|
|
"SamplerState s_diffuse : register(s0);\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 tex = t_diffuse.Sample(s_diffuse, inp.tc);\n"
|
|
"#ifdef MASK\n"
|
|
"if (tex.a < float(MASK))\n"
|
|
"discard;\n"
|
|
"#endif\n"
|
|
//FIXME: no fog, no colourmod
|
|
"return tex * inp.vcol;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultwall",
|
|
"!!permu DELUXE\n"
|
|
"!!permu FULLBRIGHT\n"
|
|
"!!permu FOG\n"
|
|
"!!permu LIGHTSTYLED\n"
|
|
"!!permu BUMP\n"
|
|
"!!permu SPECULAR\n"
|
|
"!!permu REFLECTCUBEMASK\n"
|
|
"!!cvarf r_glsl_offsetmapping_scale\n"
|
|
"!!cvarf gl_specular\n"
|
|
|
|
"#include \"sys/defs.h\"\n"
|
|
|
|
//this is what normally draws all of your walls, even with rtlights disabled
|
|
//note that the '286' preset uses drawflat_walls instead.
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
|
|
"varying vec3 eyevector;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"varying mat3 invsurface;\n"
|
|
"#endif\n"
|
|
|
|
"varying vec2 tc;\n"
|
|
"#ifdef LIGHTSTYLED\n"
|
|
//we could use an offset, but that would still need to be per-surface which would break batches
|
|
//fixme: merge attributes?
|
|
"varying vec2 lm0, lm1, lm2, lm3;\n"
|
|
"#else\n"
|
|
"varying vec2 lm0;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
|
|
"vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n"
|
|
"eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n"
|
|
"eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n"
|
|
"eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n"
|
|
"#endif\n"
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"invsurface[0] = v_svector;\n"
|
|
"invsurface[1] = v_tvector;\n"
|
|
"invsurface[2] = v_normal;\n"
|
|
"#endif\n"
|
|
"tc = v_texcoord;\n"
|
|
"lm0 = v_lmcoord;\n"
|
|
"#ifdef LIGHTSTYLED\n"
|
|
"lm1 = v_lmcoord2;\n"
|
|
"lm2 = v_lmcoord3;\n"
|
|
"lm3 = v_lmcoord4;\n"
|
|
"#endif\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
|
|
//samplers
|
|
"#define s_colourmap s_t0\n"
|
|
"uniform sampler2D s_colourmap;\n"
|
|
|
|
"#ifdef SPECULAR\n"
|
|
"uniform float cvar_gl_specular;\n"
|
|
"#endif\n"
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"#include \"sys/offsetmapping.h\"\n"
|
|
"#endif\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
//adjust texture coords for offsetmapping
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);\n"
|
|
"#define tc tcoffsetmap\n"
|
|
"#endif\n"
|
|
|
|
"#if defined(EIGHTBIT) && !defined(LIGHTSTYLED)\n"
|
|
//optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise.
|
|
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
|
|
//FIXME: this rounding is likely not correct with respect to software rendering. oh well.
|
|
"vec2 lmcoord0 = floor(lm0 * 256.0*8.0)/(256.0*8.0);\n"
|
|
"#define lm0 lmcoord0\n"
|
|
"#endif\n"
|
|
|
|
|
|
//yay, regular texture!
|
|
"gl_FragColor = texture2D(s_diffuse, tc);\n"
|
|
|
|
"#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))\n"
|
|
"vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);\n"
|
|
"#elif defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)\n"
|
|
"vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.\n"
|
|
"#endif\n"
|
|
|
|
//modulate that by the lightmap(s) including deluxemap(s)
|
|
"#ifdef LIGHTSTYLED\n"
|
|
"vec3 lightmaps;\n"
|
|
"#ifdef DELUXE\n"
|
|
"lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxmap0, lm0).rgb-0.5);\n"
|
|
"lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxmap1, lm1).rgb-0.5);\n"
|
|
"lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxmap2, lm2).rgb-0.5);\n"
|
|
"lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxmap3, lm3).rgb-0.5);\n"
|
|
"#else\n"
|
|
"lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;\n"
|
|
"lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;\n"
|
|
"lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb;\n"
|
|
"lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb;\n"
|
|
"#endif\n"
|
|
"#else\n"
|
|
"vec3 lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;\n"
|
|
//modulate by the bumpmap dot light
|
|
"#ifdef DELUXE\n"
|
|
"vec3 delux = 2.0*(texture2D(s_deluxmap, lm0).rgb-0.5);\n"
|
|
"lightmaps *= 1.0 / max(0.25, delux.z); //counter the darkening from deluxmaps\n"
|
|
"lightmaps *= dot(norm, delux);\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
|
|
//add in specular, if applicable.
|
|
"#ifdef SPECULAR\n"
|
|
"vec4 specs = texture2D(s_specular, tc);\n"
|
|
"#ifdef DELUXE\n"
|
|
//not lightstyled...
|
|
"vec3 halfdir = normalize(normalize(eyevector) + 2.0*(texture2D(s_deluxmap0, lm0).rgb-0.5)); //this norm should be the deluxemap info instead\n"
|
|
"#else\n"
|
|
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0)); //this norm should be the deluxemap info instead\n"
|
|
"#endif\n"
|
|
"float spec = pow(max(dot(halfdir, norm), 0.0), 32.0 * specs.a);\n"
|
|
"spec *= cvar_gl_specular;\n"
|
|
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
|
|
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
|
|
//we default to something that is not garish when the light value is directly infront of every single pixel.
|
|
//we can justify this difference due to the rtlight editor etc showing the *4.
|
|
"gl_FragColor.rgb += spec * specs.rgb;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"vec3 rtc = reflect(-eyevector, norm);\n"
|
|
"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n"
|
|
"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n"
|
|
"gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant.\n"
|
|
"lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.\n"
|
|
"float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated.\n"
|
|
"lightmaps -= 1.0 / 128.0; //software rendering appears to round down, so make sure we favour the lower values instead of rounding to the nearest\n"
|
|
"gl_FragColor.r = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.r)).r; //do 3 lookups. this is to cope with lit files, would be a waste to not support those.\n"
|
|
"gl_FragColor.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly.\n"
|
|
"gl_FragColor.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical.\n"
|
|
"#else\n"
|
|
//now we have our diffuse+specular terms, modulate by lightmap values.
|
|
"gl_FragColor.rgb *= lightmaps.rgb;\n"
|
|
|
|
//add on the fullbright
|
|
"#ifdef FULLBRIGHT\n"
|
|
"gl_FragColor.rgb += texture2D(s_fullbright, tc).rgb;\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
|
|
//entity modifiers
|
|
"gl_FragColor = gl_FragColor * e_colourident;\n"
|
|
|
|
//and finally hide it all if we're fogged.
|
|
"#ifdef FOG\n"
|
|
"gl_FragColor = fog4(gl_FragColor);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultwall",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float2 lmtc: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"outp.lmtc = inp.tc.zw;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_lightmap : register(t2);\n"
|
|
"SamplerState s_lightmap : register(s2);\n"
|
|
|
|
"Texture2D t_diffuse : register(s0);\n"
|
|
"SamplerState s_diffuse : register(s0);\n"
|
|
|
|
"Texture2D t_fullbright : register(s1);\n"
|
|
"SamplerState s_fullbright : register(s1);\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 result;\n"
|
|
"result = t_diffuse.Sample(s_diffuse, inp.tc);\n"
|
|
"result.rgb *= t_lightmap.Sample(s_lightmap, inp.lmtc).bgr * e_lmscale[0].rgb;\n"
|
|
"float4 fb = t_fullbright.Sample(s_fullbright, inp.tc);\n"
|
|
"result.rgb += fb.rgb * fb.a;//lerp(result.rgb, fb.rgb, fb.a);\n"
|
|
"return result;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultwarp",
|
|
"!!permu FOG\n"
|
|
"!!cvarf r_wateralpha\n"
|
|
|
|
"#include \"sys/defs.h\"\n"
|
|
|
|
//this is the shader that's responsible for drawing default q1 turbulant water surfaces
|
|
//this is expected to be moderately fast.
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"varying vec2 tc;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord.st;\n"
|
|
"#ifdef FLOW\n"
|
|
"tc.s += e_time * -0.5;\n"
|
|
"#endif\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#ifndef ALPHA\n"
|
|
"uniform float cvar_r_wateralpha;\n"
|
|
"#define USEALPHA cvar_r_wateralpha\n"
|
|
"#else\n"
|
|
"#define USEALPHA float(ALPHA)\n"
|
|
"#endif\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 ntc;\n"
|
|
"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
|
|
"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
|
|
"vec3 ts = vec3(texture2D(s_diffuse, ntc));\n"
|
|
"gl_FragColor = fog4(vec4(ts, USEALPHA));\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D9QUAKE
|
|
{QR_DIRECT3D9, 9, "defaultwarp",
|
|
"!!cvarf r_wateralpha\n"
|
|
"struct a2v {\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"struct v2f {\n"
|
|
"#ifndef FRAGMENT_SHADER\n"
|
|
"float4 pos: POSITION;\n"
|
|
"#endif\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"float4x4 m_modelviewprojection;\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"float cvar_r_wateralpha;\n"
|
|
"float e_time;\n"
|
|
"sampler s_diffuse;\n"
|
|
"float4 main (v2f inp) : COLOR0\n"
|
|
"{\n"
|
|
"float2 ntc;\n"
|
|
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
|
|
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
|
|
"float3 ts = tex2D(s_diffuse, ntc).xyz;\n"
|
|
|
|
"return float4(ts, cvar_r_wateralpha);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultwarp",
|
|
"!!cvarf r_wateralpha\n"
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
// float cvar_r_wateralpha;
|
|
// float e_time;
|
|
"SamplerState s_diffuse;\n"
|
|
"Texture2D t_diffuse;\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float2 ntc;\n"
|
|
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
|
|
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
|
|
"return t_diffuse.Sample(s_diffuse, ntc);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultgammacb",
|
|
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = pow(texture2D(s_t0, tc) * vc.g, vec4(vc.r)) + vc.b;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "drawflat_wall",
|
|
"!!cvarv r_floorcolor\n"
|
|
"!!cvarv r_wallcolor\n"
|
|
"!!permu FOG\n"
|
|
|
|
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"varying vec4 col;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec3 v_normal;\n"
|
|
"attribute vec2 v_lmcoord;\n"
|
|
"varying vec2 lm;\n"
|
|
"uniform vec3 cvar_r_wallcolor;\n"
|
|
"uniform vec3 cvar_r_floorcolor;\n"
|
|
"uniform vec4 e_lmscale;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);\n"
|
|
"lm = v_lmcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"varying vec2 lm;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = fog4(col * texture2D(s_t0, lm));\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "drawflat_wall",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float3 norm: NORMAL;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float2 lmtc: TEXCOORD1;\n"
|
|
"float4 col: TEXCOORD2;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"outp.lmtc = inp.tc.zw;\n"
|
|
"outp.col = ((inp.norm.z<0.73)?float4(0.5, 0.5, 0.5, 1):float4(0.25, 0.25, 0.5, 1));\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D t_lightmap : register(t0);\n"
|
|
"SamplerState s_lightmap : register(s0);\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return inp.col * t_lightmap.Sample(s_lightmap, inp.lmtc);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "lpp_depthnorm",
|
|
"!!permu BUMP\n"
|
|
"!!permu SKELETAL\n"
|
|
|
|
//light pre-pass rendering (defered lighting)
|
|
//this is the initial pass, that draws the surface normals and depth to the initial colour buffer
|
|
|
|
"varying vec3 norm, tang, bitang;\n"
|
|
"#if defined(BUMP)\n"
|
|
"varying vec2 tc;\n"
|
|
"#endif\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"#if defined(BUMP)\n"
|
|
"gl_Position = skeletaltransform_nst(norm, tang, bitang);\n"
|
|
"tc = v_texcoord;\n"
|
|
"#else\n"
|
|
"gl_Position = skeletaltransform_n(norm);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#if defined(BUMP)\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"#endif\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec3 onorm;\n"
|
|
"#if defined(BUMP)\n"
|
|
"vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0;\n"
|
|
"onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm);\n"
|
|
"#else\n"
|
|
"onorm = norm;\n"
|
|
"#endif\n"
|
|
"gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "lpp_light",
|
|
//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.
|
|
//fixme: no fog
|
|
|
|
"varying vec4 tf;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"tf = ftetransform();\n"
|
|
"gl_Position = tf;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform vec3 l_lightposition;\n"
|
|
"uniform mat4 m_invviewprojection;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform float l_lightradius;\n"
|
|
"vec3 calcLightWorldPos(vec2 screenPos, float depth)\n"
|
|
"{\n"
|
|
"vec4 pos;\n"
|
|
"pos.x = screenPos.x;\n"
|
|
"pos.y = screenPos.y;\n"
|
|
"pos.z = depth;\n"
|
|
"pos.w = 1.0;\n"
|
|
"pos = m_invviewprojection * pos;\n"
|
|
"return pos.xyz / pos.w;\n"
|
|
"}\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec3 lightColour = l_lightcolour.rgb;\n"
|
|
"float lightIntensity = 1.0;\n"
|
|
"float lightAttenuation = l_lightradius; // fixme: just use the light radius for now, use better near/far att math separately once working\n"
|
|
"float radiusFar = l_lightradius;\n"
|
|
"float radiusNear = l_lightradius*0.5;\n"
|
|
|
|
"vec2 fc;\n"
|
|
"fc = tf.xy / tf.w;\n"
|
|
"vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);\n"
|
|
"float depth = data.a;\n"
|
|
"vec3 norm = data.xyz;\n"
|
|
|
|
/* calc where the wall that generated this sample came from */
|
|
"vec3 worldPos = calcLightWorldPos(fc, depth);\n"
|
|
|
|
/*calc diffuse lighting term*/
|
|
"vec3 lightDir = l_lightposition - worldPos;\n"
|
|
"float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0);\n"
|
|
"float atten = (radiusFar * zdiff) / (radiusFar - radiusNear);\n"
|
|
"atten = pow(atten, 2.0);\n"
|
|
"lightDir = normalize(lightDir);\n"
|
|
"float nDotL = dot(norm, lightDir) * atten;\n"
|
|
"float lightDiffuse = max(0.0, nDotL);\n"
|
|
|
|
"gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "lpp_wall",
|
|
//the final defered lighting pass.
|
|
//the lighting values were written to some render target, which is fed into this shader, and now we draw all the wall textures with it.
|
|
|
|
"varying vec2 tc, lm;\n"
|
|
"varying vec4 tf;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec2 v_lmcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"lm = v_lmcoord;\n"
|
|
"gl_Position = tf = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"uniform sampler2D s_t2;\n"
|
|
"uniform vec4 e_lmscale;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 nst;\n"
|
|
"nst = tf.xy / tf.w;\n"
|
|
"nst = (1.0 + nst) / 2.0;\n"
|
|
"vec4 l = texture2D(s_t0, nst)*5.0;\n"
|
|
"vec4 c = texture2D(s_t1, tc);\n"
|
|
"vec3 lmsamp = texture2D(s_t2, lm).rgb*e_lmscale.rgb;\n"
|
|
"vec3 diff = l.rgb;\n"
|
|
"vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11)));\n"
|
|
"vec3 spec = chrom * l.a;\n"
|
|
"gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "postproc_fisheye",
|
|
"!!cvarf ffov\n"
|
|
|
|
//fisheye view rendering, for silly fovs that are still playable.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"texcoord = v_texcoord.xy;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform samplerCube s_t0;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform float cvar_ffov;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec3 tc; \n"
|
|
"vec2 d; \n"
|
|
"vec2 ang; \n"
|
|
"d = texcoord; \n"
|
|
"ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n"
|
|
"ang.y = -atan(d.y, d.x); \n"
|
|
"tc.x = sin(ang.x) * cos(ang.y); \n"
|
|
"tc.y = sin(ang.x) * sin(ang.y); \n"
|
|
"tc.z = cos(ang.x); \n"
|
|
"gl_FragColor = textureCube(s_t0, tc);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "postproc_panorama",
|
|
"!!cvarf ffov\n"
|
|
|
|
//panoramic view rendering, for promo map shots or whatever.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"texcoord = v_texcoord.xy;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform samplerCube s_t0;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform float cvar_ffov;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec3 tc; \n"
|
|
"float ang; \n"
|
|
"ang = texcoord.x*radians(cvar_ffov); \n"
|
|
"tc.x = sin(ang); \n"
|
|
"tc.y = -texcoord.y; \n"
|
|
"tc.z = cos(ang); \n"
|
|
"gl_FragColor = textureCube(s_t0, tc);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "postproc_laea",
|
|
"!!cvarf ffov\n"
|
|
|
|
//my attempt at lambert azimuthal equal-area view rendering, because you'll remember that name easily.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform float cvar_ffov;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"texcoord = v_texcoord.xy;\n"
|
|
|
|
//make sure the ffov cvar actually does something meaningful
|
|
"texcoord *= cvar_ffov / 90.0;\n"
|
|
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform samplerCube s_t0;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec3 tc; \n"
|
|
"vec2 d; \n"
|
|
"vec2 ang; \n"
|
|
"d = texcoord; \n"
|
|
|
|
//compute the 2d->3d projection
|
|
"float sq = d.x*d.x+d.y*d.y;\n"
|
|
"if (sq > 4.0)\n"
|
|
"gl_FragColor = vec4(0,0,0,1);\n"
|
|
"else\n"
|
|
"{\n"
|
|
"tc.x = sqrt(1.0-(sq/4.0))*d.x;\n"
|
|
"tc.y = sqrt(1.0-(sq/4.0))*d.y;\n"
|
|
"tc.z = -1.0 + (sq/2.0);\n"
|
|
|
|
"tc.y *= -1.0;\n"
|
|
"tc.z *= -1.0;\n"
|
|
|
|
"gl_FragColor = textureCube(s_t0, tc);\n"
|
|
"}\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "postproc_stereographic",
|
|
"!!cvarf ffov\n"
|
|
|
|
//stereographic view rendering, for high fovs that are still playable.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform float cvar_ffov;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"texcoord = v_texcoord.xy;\n"
|
|
|
|
//make sure the ffov cvar actually does something meaningful
|
|
"texcoord *= cvar_ffov / 90.0;\n"
|
|
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform samplerCube s_t0;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec3 tc; \n"
|
|
"vec2 d; \n"
|
|
"vec2 ang; \n"
|
|
"d = texcoord; \n"
|
|
|
|
//compute the 2d->3d projection
|
|
"float div = 1.0 + d.x*d.x + d.y*d.y;\n"
|
|
"tc.x = 2.0*d.x/div;\n"
|
|
"tc.y = -2.0*d.y/div;\n"
|
|
"tc.z = -(-1.0 + d.x*d.x + d.y*d.y)/div;\n"
|
|
|
|
"gl_FragColor = textureCube(s_t0, tc);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "rtlight",
|
|
"!!permu BUMP\n"
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
"!!permu UPPERLOWER\n"
|
|
"!!permu FOG\n"
|
|
"!!permu REFLECTCUBEMASK\n"
|
|
"!!cvarf r_glsl_offsetmapping_scale\n"
|
|
"!!cvardf r_glsl_pcf\n"
|
|
|
|
|
|
"#ifndef USE_ARB_SHADOW\n"
|
|
//fall back on regular samplers if we must
|
|
"#define sampler2DShadow sampler2D\n"
|
|
"#endif\n"
|
|
|
|
//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
|
|
|
|
"#ifndef r_glsl_pcf\n"
|
|
"#error r_glsl_pcf wasnt defined\n"
|
|
"#endif\n"
|
|
"#if r_glsl_pcf < 1\n"
|
|
"#undef r_glsl_pcf\n"
|
|
"#define r_glsl_pcf 9\n"
|
|
"#endif\n"
|
|
|
|
"#if 0 && defined(GL_ARB_texture_gather) && defined(PCF) \n"
|
|
"#extension GL_ARB_texture_gather : enable\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef UPPERLOWER\n"
|
|
"#define UPPER\n"
|
|
"#define LOWER\n"
|
|
"#endif\n"
|
|
|
|
//if there's no vertex normals known, disable some stuff.
|
|
//FIXME: this results in dupe permutations.
|
|
"#ifdef NOBUMP\n"
|
|
"#undef SPECULAR\n"
|
|
"#undef BUMP\n"
|
|
"#undef OFFSETMAPPING\n"
|
|
"#endif\n"
|
|
|
|
|
|
"varying vec2 tcbase;\n"
|
|
"varying vec3 lightvector;\n"
|
|
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
|
|
"varying vec3 eyevector;\n"
|
|
"#endif\n"
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"varying mat3 invsurface;\n"
|
|
"uniform mat4 m_model;\n"
|
|
"#endif\n"
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"varying vec4 vtexprojcoord;\n"
|
|
"#endif\n"
|
|
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"uniform mat4 l_cubematrix;\n"
|
|
"#endif\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"uniform vec3 l_lightposition;\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"#endif\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec3 n, s, t, w;\n"
|
|
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
|
|
"tcbase = v_texcoord; //pass the texture coords straight through\n"
|
|
"vec3 lightminusvertex = l_lightposition - w.xyz;\n"
|
|
"#ifdef NOBUMP\n"
|
|
//the only important thing is distance
|
|
"lightvector = lightminusvertex;\n"
|
|
"#else\n"
|
|
//the light direction relative to the surface normal, for bumpmapping.
|
|
"lightvector.x = dot(lightminusvertex, s.xyz);\n"
|
|
"lightvector.y = dot(lightminusvertex, t.xyz);\n"
|
|
"lightvector.z = dot(lightminusvertex, n.xyz);\n"
|
|
"#endif\n"
|
|
"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
|
|
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
|
|
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
|
|
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
|
|
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
|
|
"#endif\n"
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"invsurface[0] = v_svector;\n"
|
|
"invsurface[1] = v_tvector;\n"
|
|
"invsurface[2] = v_normal;\n"
|
|
"#endif\n"
|
|
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
|
|
//for texture projections/shadowmapping on dlights
|
|
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#include \"sys/fog.h\"\n"
|
|
"uniform sampler2D s_t0; //diffuse\n"
|
|
|
|
"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
|
|
"uniform sampler2D s_t1; //normalmap\n"
|
|
"#endif\n"
|
|
"#ifdef SPECULAR\n"
|
|
"uniform sampler2D s_t2; //specular\n"
|
|
"#endif\n"
|
|
"#ifdef CUBE\n"
|
|
"uniform samplerCube s_t3; //projected cubemap\n"
|
|
"#endif\n"
|
|
"#ifdef PCF\n"
|
|
"#ifdef CUBESHADOW\n"
|
|
"uniform samplerCubeShadow s_t4; //shadowmap\n"
|
|
"#else\n"
|
|
"#if 0//def GL_ARB_texture_gather\n"
|
|
"uniform sampler2D s_t4;\n"
|
|
"#else\n"
|
|
"uniform sampler2DShadow s_t4;\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"uniform sampler2D s_t5; //pants colours\n"
|
|
"uniform vec3 e_lowercolour;\n"
|
|
"#endif\n"
|
|
"#ifdef UPPER\n"
|
|
"uniform sampler2D s_t6; //shirt colours\n"
|
|
"uniform vec3 e_uppercolour;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"uniform sampler2D s_reflectmask;\n"
|
|
"uniform samplerCube s_reflectcube;\n"
|
|
"#endif\n"
|
|
|
|
|
|
"uniform float l_lightradius;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform vec3 l_lightcolourscale;\n"
|
|
"#ifdef PCF\n"
|
|
"uniform vec4 l_shadowmapproj; //light projection matrix info\n"
|
|
"uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.\n"
|
|
"vec3 ShadowmapCoord(void)\n"
|
|
"{\n"
|
|
"#ifdef SPOT\n"
|
|
//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
|
|
"return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
|
|
//#elif defined(CUBESHADOW)
|
|
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
|
|
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
|
|
"#else\n"
|
|
//figure out which axis to use
|
|
//texture is arranged thusly:
|
|
//forward left up
|
|
//back right down
|
|
"vec3 dir = abs(vtexprojcoord.xyz);\n"
|
|
//assume z is the major axis (ie: forward from the light)
|
|
"vec3 t = vtexprojcoord.xyz;\n"
|
|
"float ma = dir.z;\n"
|
|
"vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n"
|
|
"if (dir.x > ma)\n"
|
|
"{\n"
|
|
"ma = dir.x;\n"
|
|
"t = vtexprojcoord.zyx;\n"
|
|
"axis.x = 0.5;\n"
|
|
"}\n"
|
|
"if (dir.y > ma)\n"
|
|
"{\n"
|
|
"ma = dir.y;\n"
|
|
"t = vtexprojcoord.xzy;\n"
|
|
"axis.x = 2.5/3.0;\n"
|
|
"}\n"
|
|
//if the axis is negative, flip it.
|
|
"if (t.z > 0.0)\n"
|
|
"{\n"
|
|
"axis.y = 1.5/2.0;\n"
|
|
"t.z = -t.z;\n"
|
|
"}\n"
|
|
|
|
//we also need to pass the result through the light's projection matrix too
|
|
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
|
|
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
|
|
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
|
|
//also make sure we're in the right quadrant type thing
|
|
"return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
|
|
"float ShadowmapFilter(void)\n"
|
|
"{\n"
|
|
"vec3 shadowcoord = ShadowmapCoord();\n"
|
|
|
|
"#if 0//def GL_ARB_texture_gather\n"
|
|
"vec2 ipart, fpart;\n"
|
|
"#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n"
|
|
"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n"
|
|
"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n"
|
|
"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n"
|
|
"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n"
|
|
//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\n"
|
|
"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows\n"
|
|
"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.\n"
|
|
|
|
"#else\n"
|
|
"#ifdef USE_ARB_SHADOW\n"
|
|
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
|
|
"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
|
|
"#else\n"
|
|
//this will probably be a bit blocky.
|
|
"#define dosamp(x,y) float(texture2D(s_t4, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n"
|
|
"#endif\n"
|
|
"float s = 0.0;\n"
|
|
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"return s;\n"
|
|
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
|
|
"s += dosamp(-1.0, 0.0);\n"
|
|
"s += dosamp(0.0, -1.0);\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"s += dosamp(0.0, 1.0);\n"
|
|
"s += dosamp(1.0, 0.0);\n"
|
|
"return s/5.0;\n"
|
|
"#else\n"
|
|
"s += dosamp(-1.0, -1.0);\n"
|
|
"s += dosamp(-1.0, 0.0);\n"
|
|
"s += dosamp(-1.0, 1.0);\n"
|
|
"s += dosamp(0.0, -1.0);\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"s += dosamp(0.0, 1.0);\n"
|
|
"s += dosamp(1.0, -1.0);\n"
|
|
"s += dosamp(1.0, 0.0);\n"
|
|
"s += dosamp(1.0, 1.0);\n"
|
|
"return s/9.0;\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"#include \"sys/offsetmapping.h\"\n"
|
|
"#endif\n"
|
|
|
|
"void main ()\n"
|
|
"{\n"
|
|
//read raw texture samples (offsetmapping munges the tex coords first)
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n"
|
|
"#define tcbase tcoffsetmap\n"
|
|
"#endif\n"
|
|
"vec3 bases = vec3(texture2D(s_t0, tcbase));\n"
|
|
"#ifdef UPPER\n"
|
|
"vec4 uc = texture2D(s_t6, tcbase);\n"
|
|
"bases.rgb += uc.rgb*e_uppercolour*uc.a;\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"vec4 lc = texture2D(s_t5, tcbase);\n"
|
|
"bases.rgb += lc.rgb*e_lowercolour*lc.a;\n"
|
|
"#endif\n"
|
|
"#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
|
|
"vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n"
|
|
"#elif defined(REFLECTCUBEMASK)\n"
|
|
"vec3 bumps = vec3(0.0,0.0,1.0);\n"
|
|
"#endif\n"
|
|
"#ifdef SPECULAR\n"
|
|
"vec4 specs = texture2D(s_t2, tcbase);\n"
|
|
"#endif\n"
|
|
|
|
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"vec3 diff;\n"
|
|
"#ifdef NOBUMP\n"
|
|
//surface can only support ambient lighting, even for lights that try to avoid it.
|
|
"diff = bases * (l_lightcolourscale.x+l_lightcolourscale.y);\n"
|
|
"#else\n"
|
|
"vec3 nl = normalize(lightvector);\n"
|
|
"#ifdef BUMP\n"
|
|
"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));\n"
|
|
"#else\n"
|
|
//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));\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
|
|
|
|
"#ifdef SPECULAR\n"
|
|
"vec3 halfdir = normalize(normalize(eyevector) + nl);\n"
|
|
"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n"
|
|
"diff += l_lightcolourscale.z * spec * specs.rgb;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef REFLECTCUBEMASK\n"
|
|
"vec3 rtc = reflect(-eyevector, bumps);\n"
|
|
"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n"
|
|
"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n"
|
|
"diff += texture2D(s_reflectmask, tcbase).rgb * textureCube(s_reflectcube, rtc).rgb;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
/*filter the colour by the cubemap projection*/
|
|
"diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;\n"
|
|
"#endif\n"
|
|
|
|
"#if defined(SPOT)\n"
|
|
/*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;\n"
|
|
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef PCF\n"
|
|
/*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();\n"
|
|
// diff = ShadowmapCoord();
|
|
"#endif\n"
|
|
|
|
"#if defined(PROJECTION)\n"
|
|
/*2d projection, not used*/
|
|
// diff *= texture2d(s_t3, shadowcoord);
|
|
"#endif\n"
|
|
|
|
"gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n"
|
|
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
},
|
|
#endif
|
|
#ifdef D3D9QUAKE
|
|
{QR_DIRECT3D9, 9, "rtlight",
|
|
"!!permu BUMP\n"
|
|
"!!permu SPECULAR\n"
|
|
"!!permu OFFSETMAPPING\n"
|
|
"!!permu SKELETAL\n"
|
|
"!!permu FOG\n"
|
|
|
|
|
|
// texture units:
|
|
// s0=diffuse, s1=normal, s2=specular, s3=shadowmap
|
|
// custom modifiers:
|
|
// PCF(shadowmap)
|
|
// CUBE(projected cubemap)
|
|
|
|
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float3 tc: TEXCOORD0;\n"
|
|
"float3 n: NORMAL0;\n"
|
|
"float3 s: TANGENT0;\n"
|
|
"float3 t: BINORMAL0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"#ifndef FRAGMENT_SHADER\n"
|
|
"float4 pos: POSITION;\n"
|
|
"#endif\n"
|
|
"float3 tc: TEXCOORD0;\n"
|
|
"float3 lpos: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"float4x4 m_modelviewprojection;\n"
|
|
"float3 l_lightposition;\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
|
|
"float3 lightminusvertex = l_lightposition - inp.pos.xyz;\n"
|
|
"outp.lpos.x = dot(lightminusvertex, inp.s.xyz);\n"
|
|
"outp.lpos.y = dot(lightminusvertex, inp.t.xyz);\n"
|
|
"outp.lpos.z = dot(lightminusvertex, inp.n.xyz);\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"sampler s_diffuse;\n"
|
|
"float l_lightradius;\n"
|
|
"float3 l_lightcolour;\n"
|
|
"float4 main (v2f inp) : COLOR0\n"
|
|
"{\n"
|
|
"float3 col = l_lightcolour;\n"
|
|
"col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0);\n"
|
|
"float3 diff = tex2D(s_diffuse, inp.tc);\n"
|
|
"return float4(diff * col, 1);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "rtlight",
|
|
"!!permu BUMP\n"
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
"!!permu UPPERLOWER\n"
|
|
"!!permu FOG\n"
|
|
"!!cvarf r_glsl_offsetmapping_scale\n"
|
|
"!!cvardf r_glsl_pcf\n"
|
|
|
|
|
|
//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
|
|
|
|
"#undef CUBE //engine cannot load cubemaps properly with d3d yet.\n"
|
|
|
|
"#ifndef r_glsl_pcf\n"
|
|
"#error r_glsl_pcf wasn't defined\n"
|
|
"#endif\n"
|
|
"#if r_glsl_pcf < 1\n"
|
|
"#undef r_glsl_pcf\n"
|
|
"#define r_glsl_pcf 9\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef UPPERLOWER\n"
|
|
"#define UPPER\n"
|
|
"#define LOWER\n"
|
|
"#endif\n"
|
|
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float3 n: NORMAL;\n"
|
|
"float3 s: TANGENT;\n"
|
|
"float3 t: BINORMAL;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float3 lightvector: TEXCOORD1;\n"
|
|
"float3 eyevector: TEXCOORD2;\n"
|
|
"float3 vtexprojcoord: TEXCOORD3;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"float4 wpos;\n"
|
|
"wpos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, wpos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"float3 lightminusvertex = l_lightposition - wpos.xyz;\n"
|
|
"outp.lightvector.x = -dot(lightminusvertex, inp.s.xyz);\n"
|
|
"outp.lightvector.y = dot(lightminusvertex, inp.t.xyz);\n"
|
|
"outp.lightvector.z = dot(lightminusvertex, inp.n.xyz);\n"
|
|
"float3 eyeminusvertex = e_eyepos - wpos.xyz;\n"
|
|
"outp.eyevector.x = -dot(eyeminusvertex, inp.s.xyz);\n"
|
|
"outp.eyevector.y = dot(eyeminusvertex, inp.t.xyz);\n"
|
|
"outp.eyevector.z = dot(eyeminusvertex, inp.n.xyz);\n"
|
|
"outp.vtexprojcoord = mul(l_cubematrix, wpos).xyz;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
|
|
"Texture2D t_diffuse : register(t0);\n"
|
|
"Texture2D t_normalmap : register(t1);\n"
|
|
"Texture2D t_specular : register(t2);\n"
|
|
"Texture2D t_upper : register(t3);\n"
|
|
"Texture2D t_lower : register(t4);\n"
|
|
"Texture2D t_shadowmap : register(t5);\n"
|
|
"TextureCube t_projectionmap : register(t6);\n"
|
|
|
|
"SamplerState s_diffuse : register(s0);\n"
|
|
"SamplerState s_normalmap : register(s1);\n"
|
|
"SamplerState s_specular : register(s2);\n"
|
|
"SamplerState s_upper : register(s3);\n"
|
|
"SamplerState s_lower : register(s4);\n"
|
|
"SamplerComparisonState s_shadowmap : register(s5);\n"
|
|
"SamplerState s_projectionmap : register(s6);\n"
|
|
|
|
|
|
"#ifdef PCF\n"
|
|
"float3 ShadowmapCoord(float3 vtexprojcoord)\n"
|
|
"{\n"
|
|
"#ifdef SPOT\n"
|
|
//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
|
|
"vtexprojcoord.z -= 0.015;\n"
|
|
"return (vtexprojcoord.xyz + float3(1.0, 1.0, 1.0)) * float3(0.5, 0.5, 0.5);\n"
|
|
//#elif defined(CUBESHADOW)
|
|
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
|
|
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
|
|
"#else\n"
|
|
//figure out which axis to use
|
|
//texture is arranged thusly:
|
|
//forward left up
|
|
//back right down
|
|
"float3 dir = abs(vtexprojcoord.xyz);\n"
|
|
//assume z is the major axis (ie: forward from the light)
|
|
"float3 t = vtexprojcoord.xyz;\n"
|
|
"float ma = dir.z;\n"
|
|
"float3 axis = float3(0.5/3.0, 0.5/2.0, 0.5);\n"
|
|
"if (dir.x > ma)\n"
|
|
"{\n"
|
|
"ma = dir.x;\n"
|
|
"t = vtexprojcoord.zyx;\n"
|
|
"axis.x = 0.5;\n"
|
|
"}\n"
|
|
"if (dir.y > ma)\n"
|
|
"{\n"
|
|
"ma = dir.y;\n"
|
|
"t = vtexprojcoord.xzy;\n"
|
|
"axis.x = 2.5/3.0;\n"
|
|
"}\n"
|
|
//if the axis is negative, flip it.
|
|
"if (t.z > 0.0)\n"
|
|
"{\n"
|
|
"axis.y = 1.5/2.0;\n"
|
|
"t.z = -t.z;\n"
|
|
"}\n"
|
|
|
|
//we also need to pass the result through the light's projection matrix too
|
|
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
|
|
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
|
|
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
|
|
//also make sure we're in the right quadrant type thing
|
|
"return axis + ((l_shadowmapproj.xyz*t.xyz + float3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
|
|
"float ShadowmapFilter(float3 vtexprojcoord)\n"
|
|
"{\n"
|
|
"float3 shadowcoord = ShadowmapCoord(vtexprojcoord);\n"
|
|
|
|
// #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r
|
|
|
|
// #define dosamp(x,y) (t_shadowmap.Sample(s_shadowmap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z)
|
|
"#define dosamp(x,y) (t_shadowmap.SampleCmpLevelZero(s_shadowmap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z))\n"
|
|
|
|
"float s = 0.0;\n"
|
|
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"return s;\n"
|
|
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
|
|
"s += dosamp(-1.0, 0.0);\n"
|
|
"s += dosamp(0.0, -1.0);\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"s += dosamp(0.0, 1.0);\n"
|
|
"s += dosamp(1.0, 0.0);\n"
|
|
"return s * (1.0/5.0);\n"
|
|
"#else\n"
|
|
"s += dosamp(-1.0, -1.0);\n"
|
|
"s += dosamp(-1.0, 0.0);\n"
|
|
"s += dosamp(-1.0, 1.0);\n"
|
|
"s += dosamp(0.0, -1.0);\n"
|
|
"s += dosamp(0.0, 0.0);\n"
|
|
"s += dosamp(0.0, 1.0);\n"
|
|
"s += dosamp(1.0, -1.0);\n"
|
|
"s += dosamp(1.0, 0.0);\n"
|
|
"s += dosamp(1.0, 1.0);\n"
|
|
"return s * (1.0/9.0);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float2 tc = inp.tc; //TODO: offsetmapping.\n"
|
|
|
|
"float4 base = t_diffuse.Sample(s_diffuse, tc);\n"
|
|
"#ifdef BUMP\n"
|
|
"float4 bump = t_normalmap.Sample(s_normalmap, tc);\n"
|
|
"bump.rgb = normalize(bump.rgb - 0.5);\n"
|
|
"#else\n"
|
|
"float4 bump = float4(0, 0, 1, 0);\n"
|
|
"#endif\n"
|
|
"float4 spec = t_specular.Sample(s_specular, tc);\n"
|
|
"#ifdef CUBE\n"
|
|
"float4 cubemap = t_projectionmap.Sample(s_projectionmap, inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"float4 lower = t_lower.Sample(s_lower, tc);\n"
|
|
"base += lower;\n"
|
|
"#endif\n"
|
|
"#ifdef UPPER\n"
|
|
"float4 upper = t_upper.Sample(s_upper, tc);\n"
|
|
"base += upper;\n"
|
|
"#endif\n"
|
|
|
|
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"float3 nl = normalize(inp.lightvector);\n"
|
|
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
|
|
"float3 halfdir = normalize(normalize(inp.eyevector) + nl);\n"
|
|
"float specscale = pow(max(dot(halfdir, bump.rgb), 0.0), 32.0 * spec.a);\n"
|
|
|
|
"float4 result;\n"
|
|
"result.a = base.a;\n"
|
|
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
|
|
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
|
|
|
|
"result.rgb *= lightscale * l_colour; //fade light by distance and light colour.\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef PCF\n"
|
|
"result.rgb *= ShadowmapFilter(inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
|
|
//TODO: fog
|
|
"return result;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "underwaterwarp",
|
|
"!!cvarf r_waterwarp\n"
|
|
|
|
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
|
|
//its generally expected to warp the view a little.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 v_stc;\n"
|
|
"varying vec2 v_warp;\n"
|
|
"varying vec2 v_edge;\n"
|
|
"uniform float e_time;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);\n"
|
|
"v_warp.s = e_time * 0.25 + v_texcoord.s;\n"
|
|
"v_warp.t = e_time * 0.25 + v_texcoord.t;\n"
|
|
"v_edge = v_texcoord.xy;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"varying vec2 v_stc;\n"
|
|
"varying vec2 v_warp;\n"
|
|
"varying vec2 v_edge;\n"
|
|
"uniform sampler2D s_t0;/*$currentrender*/\n"
|
|
"uniform sampler2D s_t1;/*warp image*/\n"
|
|
"uniform sampler2D s_t2;/*edge image*/\n"
|
|
"uniform vec4 e_rendertexturescale;\n"
|
|
"uniform float cvar_r_waterwarp;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;\n"
|
|
"vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;\n"
|
|
"vec2 temp = v_stc + offset.xy * amp;\n"
|
|
"gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "menutint",
|
|
"!!cvari r_menutint_inverse\n"
|
|
"!!cvarv r_menutint\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform vec4 e_rendertexturescale;\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
"texcoord.x = v_texcoord.x*e_rendertexturescale.x;\n"
|
|
"texcoord.y = (1.0-v_texcoord.y)*e_rendertexturescale.y;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
|
|
"varying vec2 texcoord;\n"
|
|
"uniform vec3 cvar_r_menutint;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform int cvar_r_menutint_inverse;\n"
|
|
"const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\n"
|
|
"const vec3 invertvec = vec3(1.0, 1.0, 1.0);\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
"vec3 texcolor = texture2D(s_t0, texcoord).rgb;\n"
|
|
"float luminance = dot(lumfactors, texcolor);\n"
|
|
"texcolor = vec3(luminance, luminance, luminance);\n"
|
|
"texcolor *= cvar_r_menutint;\n"
|
|
"texcolor = (cvar_r_menutint_inverse > 0) ? (invertvec - texcolor) : texcolor;\n"
|
|
"gl_FragColor = vec4(texcolor, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "terrain",
|
|
"!!permu FOG\n"
|
|
"#include \"sys/fog.h\"\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec2 lm;\n"
|
|
"varying vec4 vc;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"varying vec3 lightvector;\n"
|
|
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
// varying vec3 eyevector;
|
|
// #endif
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"varying vec4 vtexprojcoord;\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"uniform vec3 l_lightposition;\n"
|
|
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
// uniform vec3 e_eyepos;
|
|
// #endif
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"uniform mat4 l_cubematrix;\n"
|
|
"#endif\n"
|
|
"attribute vec3 v_normal;\n"
|
|
"attribute vec3 v_svector;\n"
|
|
"attribute vec3 v_tvector;\n"
|
|
"#endif\n"
|
|
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec2 v_lmcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"tc = v_texcoord.st;\n"
|
|
"lm = v_lmcoord.st;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
//light position is in model space, which is handy.
|
|
"vec3 lightminusvertex = l_lightposition - v_position.xyz;\n"
|
|
|
|
//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes.
|
|
"lightvector = lightminusvertex;\n"
|
|
// lightvector.x = dot(lightminusvertex, v_svector.xyz);
|
|
// lightvector.y = dot(lightminusvertex, v_tvector.xyz);
|
|
// lightvector.z = dot(lightminusvertex, v_normal.xyz);
|
|
|
|
// #if defined(SPECULAR)||defined(OFFSETMAPPING)
|
|
// vec3 eyeminusvertex = e_eyepos - v_position.xyz;
|
|
// eyevector.x = dot(eyeminusvertex, v_svector.xyz);
|
|
// eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
|
|
// eyevector.z = dot(eyeminusvertex, v_normal.xyz);
|
|
// #endif
|
|
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
|
|
//for texture projections/shadowmapping on dlights
|
|
"vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
//four texture passes
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"uniform sampler2D s_t2;\n"
|
|
"uniform sampler2D s_t3;\n"
|
|
|
|
//mix values
|
|
"uniform sampler2D s_t4;\n"
|
|
|
|
"#ifdef PCF\n"
|
|
"uniform sampler2DShadow s_t5;\n"
|
|
"#include \"sys/pcf.h\"\n"
|
|
"#endif\n"
|
|
"#ifdef CUBE\n"
|
|
"uniform samplerCube s_t6;\n"
|
|
"#endif\n"
|
|
|
|
//light levels
|
|
"uniform vec4 e_lmscale;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"uniform float l_lightradius;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform vec3 l_lightcolourscale;\n"
|
|
"#endif\n"
|
|
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"vec4 r;\n"
|
|
"vec4 m = texture2D(s_t4, lm);\n"
|
|
|
|
"r = texture2D(s_t0, tc)*m.r;\n"
|
|
"r += texture2D(s_t1, tc)*m.g;\n"
|
|
"r += texture2D(s_t2, tc)*m.b;\n"
|
|
"r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n"
|
|
|
|
//vertex colours provide a scaler that applies even through rtlights.
|
|
"r *= vc;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"vec3 nl = normalize(lightvector);\n"
|
|
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"vec3 diff;\n"
|
|
// #ifdef BUMP
|
|
// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
|
|
// #else
|
|
"colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
|
|
// #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
|
|
|
|
|
|
|
|
"#if defined(SPOT)\n"
|
|
"if (vtexprojcoord.w < 0.0) discard;\n"
|
|
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n"
|
|
"colorscale *= 1.0-(dot(spot,spot));\n"
|
|
"#endif\n"
|
|
"#ifdef PCF\n"
|
|
"colorscale *= ShadowmapFilter(s_t5);\n"
|
|
"#endif\n"
|
|
|
|
"r.rgb *= colorscale * l_lightcolour;\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;\n"
|
|
"#endif\n"
|
|
|
|
"gl_FragColor = fog4additive(r);\n"
|
|
"#else\n"
|
|
//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
|
|
"r *= e_lmscale*vec4(m.aaa,1.0);\n"
|
|
"gl_FragColor = fog4(r);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "terrain",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float2 lmtc: TEXCOORD1;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"float3 vtexprojcoord: TEXCOORD2;\n"
|
|
"float3 vtexprojcoord: TEXCOORD2;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"outp.lmtc = inp.tc.zw;\n"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D shaderTexture[7];\n"
|
|
"SamplerState SampleType[7];\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 result;\n"
|
|
|
|
"float4 base = shaderTexture[0].Sample(SampleType[0], inp.tc);\n"
|
|
"#ifdef BUMP\n"
|
|
"float4 bump = shaderTexture[1].Sample(SampleType[1], inp.tc);\n"
|
|
"#else\n"
|
|
"float4 bump = float4(0, 0, 1, 0);\n"
|
|
"#endif\n"
|
|
"float4 spec = shaderTexture[2].Sample(SampleType[2], inp.tc);\n"
|
|
"#ifdef CUBE\n"
|
|
"float4 cubemap = shaderTexture[3].Sample(SampleType[3], inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
//shadowmap 2d
|
|
"#ifdef LOWER\n"
|
|
"float4 lower = shaderTexture[5].Sample(SampleType[5], inp.tc);\n"
|
|
"base += lower;\n"
|
|
"#endif\n"
|
|
"#ifdef UPPER\n"
|
|
"float4 upper = shaderTexture[6].Sample(SampleType[6], inp.tc);\n"
|
|
"base += upper;\n"
|
|
"#endif\n"
|
|
|
|
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"float3 nl = normalize(inp.lightvector);\n"
|
|
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
|
|
"float3 halfdir = normalize(normalize(eyevector) + nl);\n"
|
|
"float specscale = pow(max(dot(halfdir, bumps), 0.0), 32.0 * spec.a);\n"
|
|
|
|
"result.a = base.a;\n"
|
|
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
|
|
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
|
|
|
|
"result.rgb *= lightscale; //fade light by distance\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
|
|
"#endif\n"
|
|
|
|
"return result;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|