/*
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"
"!!cvarf r_bloom_retain=1.0\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"
"uniform float cvar_r_bloom_retain;\n"
"void main ()\n"
"{\n"
"gl_FragColor = \n"
"cvar_r_bloom_retain * 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"
"#ifdef PREMUL\n"
"inp.vcol.rgb *= inp.vcol.a;\n"
"#endif\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 D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultskin",
"!!permu FRAMEBLEND\n"
"!!permu UPPERLOWER\n"
"struct a2v\n"
"{\n"
"float3 pos: POSITION0;\n"
"#ifdef FRAMEBLEND\n"
"float3 pos2: POSITION1;\n"
"#endif\n"
"float2 tc: TEXCOORD0;\n"
"float3 normal: NORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float2 tc: TEXCOORD0;\n"
"float3 light: TEXCOORD1;\n"
"};\n"

//#include <ftedefs.h>

"#ifdef VERTEX_SHADER\n"
"float3 e_light_dir;\n"
"float3 e_light_mul;\n"
"float3 e_light_ambient;\n"
"float2 e_vblend;\n"
"float4x4  m_model;\n"
"float4x4  m_view;\n"
"float4x4  m_projection;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"float4 pos;\n"
"#ifdef FRAMEBLEND\n"
"pos = float4(e_vblend.x*inp.pos + e_vblend.y*inp.pos2, 1);\n"
"#else\n"
"pos = float4(inp.pos, 1);\n"
"#endif\n"
"outp.pos = mul(m_model, pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"

"float d = dot(inp.normal, e_light_dir);\n"
"outp.light = e_light_ambient + (d * e_light_mul);\n"
"outp.tc = inp.tc.xy;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float4 e_colourident;\n"
"float3 e_uppercolour;\n"
"float3 e_lowercolour;\n"
"sampler s_diffuse; /*diffuse*/\n"
"sampler s_upper; /*upper*/\n"
"sampler s_lower; /*lower*/\n"
"sampler s_fullbright; /*fullbright*/\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 col;\n"
"col = tex2D(s_diffuse, inp.tc);\n"
"#ifdef UPPER\n"
"float4 uc = tex2D(s_upper, inp.tc);\n"
"col.rgb += uc.rgb*e_uppercolour * uc.a;\n"
"#endif\n"
"#ifdef LOWER\n"
"float4 lc = tex2D(s_lower, inp.tc);\n"
"col.rgb += lc.rgb*e_lowercolour * lc.a;\n"
"#endif\n"
"col.rgb *= inp.light;\n"
"#ifdef FULLBRIGHT\n"
"float4 fb = tex2D(s_fullbright, inp.tc);\n"
"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n"
"#endif\n"
"return col * e_colourident;\n"
//		return fog4(col * e_colourident);
"}\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",
"!!permu FOG\n"
"#include \"sys/fog.h\"\n"

//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 = fog3((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, "fxaa",
//
//This shader implements super-sampled anti-aliasing.
//

"varying vec2 texcoord;\n"

"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"void main()\n"
"{\n"
"texcoord = v_texcoord.xy;\n"
"texcoord.y = 1.0 - texcoord.y;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform vec2 e_sourcesize;\n"

"void main( void )\n"
"{\n"
"float FXAA_SPAN_MAX = 8.0;\n"
"float FXAA_REDUCE_MUL = 1.0/8.0;\n"
"float FXAA_REDUCE_MIN = 1.0/128.0;\n"

"vec3 rgbNW=texture2D(s_t0,texcoord+(vec2(-1.0,-1.0)/e_sourcesize)).xyz;\n"
"vec3 rgbNE=texture2D(s_t0,texcoord+(vec2(1.0,-1.0)/e_sourcesize)).xyz;\n"
"vec3 rgbSW=texture2D(s_t0,texcoord+(vec2(-1.0,1.0)/e_sourcesize)).xyz;\n"
"vec3 rgbSE=texture2D(s_t0,texcoord+(vec2(1.0,1.0)/e_sourcesize)).xyz;\n"
"vec3 rgbM=texture2D(s_t0,texcoord).xyz;\n"

"vec3 luma=vec3(0.299, 0.587, 0.114);\n"
"float lumaNW = dot(rgbNW, luma);\n"
"float lumaNE = dot(rgbNE, luma);\n"
"float lumaSW = dot(rgbSW, luma);\n"
"float lumaSE = dot(rgbSE, luma);\n"
"float lumaM  = dot(rgbM,  luma);\n"

"float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n"
"float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n"

"vec2 dir;\n"
"dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n"
"dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n"

"float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n"

"float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);\n"

"dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),\n"
"max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n"
"dir * rcpDirMin)) / e_sourcesize;\n"

"vec3 rgbA = (1.0/2.0) * (texture2D(s_t0, texcoord.xy + dir * (1.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (2.0/3.0 - 0.5)).xyz);\n"
"vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (texture2D(s_t0, texcoord.xy + dir * (0.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (3.0/3.0 - 0.5)).xyz);\n"
"float lumaB = dot(rgbB, luma);\n"

"if((lumaB < lumaMin) || (lumaB > lumaMax))\n"
"gl_FragColor.xyz=rgbA;\n"
"else\n"
"gl_FragColor.xyz=rgbB;\n"
"gl_FragColor.a = 1.0;\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 D3D11QUAKE
{QR_DIRECT3D11, 11, "menutint",
"!!cvard3 r_menutint=0.2 0.2 0.2\n"
"!!cvardf r_menutint_inverse=0.0\n"

"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"
"static const float3 lumfactors = float3 (0.299, 0.587, 0.114);\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 texcolor = t_t0.Sample(s_t0, inp.tc);\n"
"float luminance = dot(lumfactors, texcolor.rgb);\n"
"texcolor.rgb = float3(luminance, luminance, luminance);\n"
"texcolor.rgb *= r_menutint;\n"
"texcolor.rgb = (r_menutint_inverse > 0) ? (1.0 - texcolor.rgb) : texcolor.rgb;\n"

"return texcolor * inp.vcol;\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
