/* 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 \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 \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 "#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 \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 \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 \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 \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 \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 \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 \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_diffuse; //diffuse\n" "#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" "uniform sampler2D s_normalmap; //normalmap\n" "#endif\n" "#ifdef SPECULAR\n" "uniform sampler2D s_specular; //specular\n" "#endif\n" "#ifdef CUBE\n" "uniform samplerCube s_projectionmap; //projected cubemap\n" "#endif\n" "#ifdef PCF\n" "#ifdef CUBESHADOW\n" "uniform samplerCubeShadow s_shadowmap; //shadowmap\n" "#else\n" "#if 0//def GL_ARB_texture_gather\n" "uniform sampler2D s_shadowmap;\n" "#else\n" "uniform sampler2DShadow s_shadowmap;\n" "#endif\n" "#endif\n" "#endif\n" "#ifdef LOWER\n" "uniform sampler2D s_lower; //pants colours\n" "uniform vec3 e_lowercolour;\n" "#endif\n" "#ifdef UPPER\n" "uniform sampler2D s_upper; //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_shadowmap, 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_shadowmap, 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_shadowmap, 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_shadowmap, 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_normalmap, tcbase, eyevector);\n" "#define tcbase tcoffsetmap\n" "#endif\n" "#if defined(FLAT)\n" "vec3 bases = vec3(1.0);\n" "#else\n" "vec3 bases = vec3(texture2D(s_diffuse, tcbase));\n" "#endif\n" "#ifdef UPPER\n" "vec4 uc = texture2D(s_upper, tcbase);\n" "bases.rgb += uc.rgb*e_uppercolour*uc.a;\n" "#endif\n" "#ifdef LOWER\n" "vec4 lc = texture2D(s_lower, 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_normalmap, 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_specular, 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_projectionmap, 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_projectionmap, 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 \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 \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 \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 #ifdef GLQUAKE {QR_OPENGL, 110, "fixedemu", //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. "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "varying vec2 tc;\n" "#ifndef UC\n" "attribute vec4 v_colour;\n" "varying vec4 vc;\n" "#endif\n" "void main ()\n" "{\n" "tc = v_texcoord;\n" "#ifndef UC\n" "vc = v_colour;\n" "#endif\n" "gl_Position = ftetransform();\n" "}\n" "#endif\n" "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D s_t0;\n" "varying vec2 tc;\n" "#ifndef UC\n" "varying vec4 vc;\n" "#else\n" "uniform vec4 s_colour;\n" "#define vc s_colour\n" "#endif\n" "float e_time;\n" "void main ()\n" "{\n" "vec4 fc = texture2D(s_t0, tc) * vc;\n" "#ifdef ALPHATEST\n" "if (!(fc.a ALPHATEST))\n" "discard;\n" "#endif\n" "gl_FragColor = fc;\n" "}\n" "#endif\n" }, #endif