mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-23 04:11:53 +00:00
2201b920c8
added frag message filter, and dedicated frag tracker. added 'windowed consoles' for social-type stuff without depending upon csqc mods for it. added in_deviceids command which allows listing/renumbering device ids. slider widgets now support inverted ranges, so gamma selection isn't so weird. fix top/bottom colour selection bug. software banding feature is now part of the 'software' preset (now that it supports mipmaps). support for loading .maps, and editing their brushes etc (with appropriate qc mod). 'map mymap.map' to use. expect problems with missing wads and replacement textures overriding them and messing up texture scales. snd_inactive is now default. fix threading issue with wavs, no more error from 0-sample-but-otherwise-valid wavs. added -makeinstaller option to embed a manifest inside the exe (and icon). the resulting program will insist on installing the game if its run from outside a valid basedir. framegroup support for q1mdl. textures are now loaded on multiple worker threads, for reduced load times. moo har har. netgraph shows packet+byte rates too. added r_lightstylescale, pretty similar to contrast, but doesn't impose any framerate cost, but may have overbrighting issues. r_softwarebanding now works on q2bsp too. fixed crepuscular lights. gzip transfer encoding is performed while downloading, instead of inducing stalls. FINALLY fix ezquake download compat issue (dimman found the issue). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4851 fc73d0e0-1445-4013-8a0c-d673dee63da5
2603 lines
69 KiB
C
2603 lines
69 KiB
C
/*
|
|
WARNING: THIS FILE IS GENERATED BY 'generatebuiltinsl.c'.
|
|
YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|
*/
|
|
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "altwater",
|
|
"!!cvarf r_glsl_turbscale\n"
|
|
//modifier: REFLECT (s_t2 is a reflection instead of diffusemap)
|
|
//modifier: STRENGTH (0.1 = fairly gentle, 0.2 = big waves)
|
|
//modifier: FRESNEL (5=water)
|
|
//modifier: TXSCALE (0.2 - wave strength)
|
|
//modifier: RIPPLEMAP (s_t3 contains a ripplemap
|
|
//modifier: TINT (some colour value)
|
|
|
|
"#ifndef FRESNEL\n"
|
|
"#define FRESNEL 5.0\n"
|
|
"#endif\n"
|
|
"#ifndef STRENGTH\n"
|
|
"#define STRENGTH 0.1\n"
|
|
"#endif\n"
|
|
"#ifndef TXSCALE\n"
|
|
"#define TXSCALE 0.2\n"
|
|
"#endif\n"
|
|
"#ifndef TINT\n"
|
|
"#define TINT vec3(0.7, 0.8, 0.7)\n"
|
|
"#endif\n"
|
|
"#ifndef FOGTINT\n"
|
|
"#define FOGTINT vec3(0.2, 0.3, 0.2)\n"
|
|
"#endif\n"
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 tf;\n"
|
|
"varying vec3 norm;\n"
|
|
"varying vec3 eye;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec3 v_normal;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"tc = v_texcoord.st;\n"
|
|
"tf = ftetransform();\n"
|
|
"norm = v_normal;\n"
|
|
"eye = e_eyepos - v_position.xyz;\n"
|
|
"gl_Position = tf;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#define s_refract s_t0\n"
|
|
"#define s_reflect s_t1\n"
|
|
"#define s_ripplemap s_t2\n"
|
|
"#define s_refractdepth s_t3\n"
|
|
|
|
"uniform float cvar_r_glsl_turbscale;\n"
|
|
"uniform sampler2D s_normalmap;\n"
|
|
"uniform sampler2D s_diffuse;\n"
|
|
"uniform sampler2D s_refract; //refract\n"
|
|
"uniform sampler2D s_reflect; //reflection\n"
|
|
"uniform sampler2D s_refractdepth; //refraction depth\n"
|
|
"uniform sampler2D s_ripplemap; //ripplemap\n"
|
|
|
|
"uniform float e_time;\n"
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"vec2 stc, ntc;\n"
|
|
"vec3 n, refr, refl;\n"
|
|
"float fres;\n"
|
|
"float depth;\n"
|
|
"stc = (1.0 + (tf.xy / tf.w)) * 0.5;\n"
|
|
//hack the texture coords slightly so that there are no obvious gaps
|
|
"stc.t -= 1.5*norm.z/1080.0;\n"
|
|
|
|
//apply q1-style warp, just for kicks
|
|
"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
|
|
"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
|
|
|
|
//generate the two wave patterns from the normalmap
|
|
"n = (texture2D(s_normalmap, TXSCALE*tc + vec2(e_time*0.1, 0.0)).xyz);\n"
|
|
"n += (texture2D(s_normalmap, TXSCALE*tc - vec2(0, e_time*0.097)).xyz);\n"
|
|
"n -= 1.0 - 4.0/256.0;\n"
|
|
|
|
"#ifdef RIPPLEMAP\n"
|
|
"n += texture2D(s_ripplemap, stc).rgb*3.0;\n"
|
|
"#endif\n"
|
|
|
|
//the fresnel term decides how transparent the water should be
|
|
"fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));\n"
|
|
|
|
"#ifdef DEPTH\n"
|
|
"float far = #include \"cvar/gl_maxdist\";\n"
|
|
"float near = #include \"cvar/gl_mindist\";\n"
|
|
//get depth value at the surface
|
|
"float sdepth = gl_FragCoord.z;\n"
|
|
"sdepth = (2.0*near) / (far + near - sdepth * (far - near));\n"
|
|
"sdepth = mix(near, far, sdepth);\n"
|
|
|
|
//get depth value at the ground beyond the surface.
|
|
"float gdepth = texture2D(s_refractdepth, stc).x;\n"
|
|
"gdepth = (2.0*near) / (far + near - gdepth * (far - near));\n"
|
|
"if (gdepth >= 0.5)\n"
|
|
"{\n"
|
|
"gdepth = sdepth;\n"
|
|
"depth = 0.0;\n"
|
|
"}\n"
|
|
"else\n"
|
|
"{\n"
|
|
"gdepth = mix(near, far, gdepth);\n"
|
|
"depth = gdepth - sdepth;\n"
|
|
"}\n"
|
|
|
|
//reduce the normals in shallow water (near walls, reduces the pain of linear sampling)
|
|
"if (depth < 100.0)\n"
|
|
"n *= depth/100.0;\n"
|
|
"#else\n"
|
|
"depth = 1.0;\n"
|
|
"#endif \n"
|
|
|
|
|
|
//refraction image (and water fog, if possible)
|
|
"refr = texture2D(s_refract, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT;\n"
|
|
"#ifdef DEPTH\n"
|
|
"refr = mix(refr, FOGTINT, min(depth/4096.0, 1.0));\n"
|
|
"#endif\n"
|
|
|
|
//reflection/diffuse
|
|
"#ifdef REFLECT\n"
|
|
"refl = texture2D(s_reflect, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb;\n"
|
|
"#else\n"
|
|
"refl = texture2D(s_diffuse, ntc).xyz;\n"
|
|
"#endif\n"
|
|
//FIXME: add specular
|
|
|
|
//interplate by fresnel
|
|
"refr = mix(refr, refl, fres);\n"
|
|
|
|
//done
|
|
"gl_FragColor = vec4(refr, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_blur",
|
|
//apply gaussian filter
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
/*offset should be 1.2 pixels away from the center*/
|
|
"uniform vec3 e_glowmod;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor =\n"
|
|
"0.3125 * texture2D(s_t0, tc - e_glowmod.st) +\n"
|
|
"0.375 * texture2D(s_t0, tc) +\n"
|
|
"0.3125 * texture2D(s_t0, tc + e_glowmod.st);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_filter",
|
|
"!!cvarv r_bloom_filter\n"
|
|
//the bloom filter
|
|
//filter out any texels which are not to bloom
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform vec3 cvar_r_bloom_filter;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor.rgb = (texture2D(s_t0, tc).rgb - cvar_r_bloom_filter)/(1.0-cvar_r_bloom_filter);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "bloom_final",
|
|
"!!cvarf r_bloom\n"
|
|
//add them together
|
|
//optionally apply tonemapping
|
|
|
|
"varying vec2 tc;\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"uniform sampler2D s_t2;\n"
|
|
"uniform sampler2D s_t3;\n"
|
|
"uniform float cvar_r_bloom;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = \n"
|
|
"texture2D(s_t0, tc) +\n"
|
|
"cvar_r_bloom*(\n"
|
|
"texture2D(s_t1, tc) +\n"
|
|
"texture2D(s_t2, tc) +\n"
|
|
"texture2D(s_t3, tc)\n"
|
|
") ;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "colourtint",
|
|
//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example)
|
|
"varying vec4 tf;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = tf = vec4(v_position.xy,-1.0, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler3D s_t1;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec2 fc;\n"
|
|
"fc = tf.xy / tf.w;\n"
|
|
"vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb;\n"
|
|
"#define LUTSIZE 16.0\n"
|
|
"vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE);\n"
|
|
"vec3 bias = vec3(1.0/(2.0*LUTSIZE));\n"
|
|
"gl_FragColor = texture3D(s_t1, raw * scale + bias);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_opaque",
|
|
//opaque surfaces are drawn to the render target to mask out skies
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_rays",
|
|
"!!cvarf crep_decay\n"
|
|
"!!cvarf crep_density\n"
|
|
"!!cvarf crep_weight\n"
|
|
|
|
//this is a post-processing shader, drawn in 2d
|
|
//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky)
|
|
//this shader then just smudges the sky out a bit as though its coming from the sun or whatever through the clouds.
|
|
//yoinked from http://fabiensanglard.net/lightScattering/index.php
|
|
|
|
"varying vec2 tc;\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"gl_Position = vec4(v_position, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"const float crep_decay = 0.94;\n"
|
|
"const float crep_density = 0.5;\n"
|
|
"const float crep_weight = 0.2;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform vec3 l_lightscreen;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"const int NUM_SAMPLES = 100;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
"vec2 deltaTextCoord = vec2(tc.st - l_lightscreen.xy);\n"
|
|
"vec2 textCoo = tc.st;\n"
|
|
"deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density;\n"
|
|
"float illuminationDecay = 1.0;\n"
|
|
"gl_FragColor = vec4(0.0,0.0,0.0,0.0);\n"
|
|
"for(int i=0; i < NUM_SAMPLES ; i++)\n"
|
|
"{\n"
|
|
"textCoo -= deltaTextCoord;\n"
|
|
"vec4 sample = texture2D(s_t0, textCoo);\n"
|
|
"sample *= illuminationDecay * crep_weight;\n"
|
|
"gl_FragColor += sample;\n"
|
|
"illuminationDecay *= crep_decay;\n"
|
|
"}\n"
|
|
"gl_FragColor *= vec4(l_lightcolour, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "crepuscular_sky",
|
|
//pretty much a regular sky shader
|
|
//though in reality we should render a sun circle in the middle.
|
|
//still, its kinda cool to have scrolling clouds masking out parts of the sun.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"varying vec3 pos;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"pos = v_position.xyz;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform float e_time;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"varying vec3 pos;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 tccoord;\n"
|
|
"vec3 dir = pos - e_eyepos;\n"
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"vec4 clouds = texture2D(s_t1, tccoord);\n"
|
|
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "depthonly",
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
|
|
//standard shader used for drawing shadowmap depth.
|
|
//also used for masking off portals and other things that want depth and no colour.
|
|
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
|
//the vertex shader is responsible for calculating lighting values.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = skeletaltransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
//must always draw something, supposedly. It might as well be black.
|
|
"gl_FragColor = vec4(0, 0, 0, 1);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "depthonly",
|
|
//used for generating shadowmaps and stuff that draws nothing.
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float3 normal: NORMAL;\n"
|
|
"#ifdef MASK\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"#endif\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"#ifdef MASK\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"#endif\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"
|
|
|
|
"#ifdef MASK\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"#endif\n"
|
|
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#ifdef MASK\n"
|
|
"Texture2D shaderTexture[1];\n"
|
|
"SamplerState SampleType[1];\n"
|
|
"#endif\n"
|
|
|
|
"#if LEVEL < 1000\n"
|
|
//pre dx10 requires that we ALWAYS write to a target.
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"#else\n"
|
|
//but on 10, it'll write depth automatically and we don't care about colour.
|
|
"void main (v2f inp) //dx10-level\n"
|
|
"#endif\n"
|
|
"{\n"
|
|
|
|
"#ifdef MASK\n"
|
|
"float alpha = shaderTexture[0].Sample(SampleType[0], inp.tc).a;\n"
|
|
"#ifndef MASKOP\n"
|
|
"#define MASKOP >= //drawn if (alpha OP ref) is true.\n"
|
|
"#endif\n"
|
|
//support for alpha masking
|
|
"if (!(alpha MASKOP MASK))\n"
|
|
"discard;\n"
|
|
"#endif\n"
|
|
|
|
"#if LEVEL < 1000\n"
|
|
"return float4(0, 0, 0, 1);\n"
|
|
"#endif\n"
|
|
"}\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_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"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D shaderTexture;\n"
|
|
"SamplerState SampleType;\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return shaderTexture.Sample(SampleType, inp.tc) * inp.vcol;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultadditivesprite",
|
|
"!!permu FOG\n"
|
|
|
|
//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing.
|
|
//includes fog, apparently.
|
|
|
|
"#include \"sys/fog.h\"\n"
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"tc = v_texcoord;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec4 vc;\n"
|
|
"uniform vec4 e_colourident;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultskin",
|
|
"!!permu FULLBRIGHT\n"
|
|
"!!permu UPPERLOWER\n"
|
|
"!!permu FRAMEBLEND\n"
|
|
"!!permu SKELETAL\n"
|
|
"!!permu FOG\n"
|
|
"!!permu BUMP\n"
|
|
"!!cvarf r_glsl_offsetmapping_scale\n"
|
|
"!!cvarf gl_specular\n"
|
|
|
|
"#include \"sys/defs.h\"\n"
|
|
|
|
//standard shader used for models.
|
|
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
|
//the vertex shader is responsible for calculating lighting values.
|
|
|
|
"varying vec2 tc;\n"
|
|
"varying vec3 light;\n"
|
|
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
|
|
"varying vec3 eyevector;\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"#include \"sys/skeletal.h\"\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n"
|
|
"vec3 n, s, t, w;\n"
|
|
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
|
|
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
|
|
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
|
|
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
|
|
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
|
|
"#else\n"
|
|
"vec3 n;\n"
|
|
"gl_Position = skeletaltransform_n(n);\n"
|
|
"#endif\n"
|
|
|
|
"float d = dot(n,e_light_dir);\n"
|
|
"if (d < 0.0) //vertex shader. this might get ugly, but I don't really want to make it per vertex.\n"
|
|
"d = 0.0; //this avoids the dark side going below the ambient level.\n"
|
|
"light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
|
|
"tc = v_texcoord;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"#include \"sys/fog.h\"\n"
|
|
|
|
"#if defined(SPECULAR)\n"
|
|
"uniform float cvar_gl_specular;\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"#include \"sys/offsetmapping.h\"\n"
|
|
"#endif\n"
|
|
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec4 col, sp;\n"
|
|
|
|
"#ifdef OFFSETMAPPING\n"
|
|
"vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);\n"
|
|
"#define tc tcoffsetmap\n"
|
|
"#endif\n"
|
|
|
|
"col = texture2D(s_diffuse, tc);\n"
|
|
"#ifdef UPPER\n"
|
|
"vec4 uc = texture2D(s_upper, tc);\n"
|
|
"col.rgb += uc.rgb*e_uppercolour*uc.a;\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"vec4 lc = texture2D(s_lower, tc);\n"
|
|
"col.rgb += lc.rgb*e_lowercolour*lc.a;\n"
|
|
"#endif\n"
|
|
|
|
"#if defined(BUMP) && defined(SPECULAR)\n"
|
|
"vec3 bumps = normalize(vec3(texture2D(s_normalmap, tc)) - 0.5);\n"
|
|
"vec4 specs = texture2D(s_specular, tc);\n"
|
|
|
|
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0));\n"
|
|
"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n"
|
|
"col.rgb += cvar_gl_specular * spec * specs.rgb;\n"
|
|
"#endif\n"
|
|
|
|
"col.rgb *= light;\n"
|
|
|
|
"#ifdef FULLBRIGHT\n"
|
|
"vec4 fb = texture2D(s_fullbright, tc);\n"
|
|
// col.rgb = mix(col.rgb, fb.rgb, fb.a);
|
|
"col.rgb += fb.rgb * fb.a;\n"
|
|
"#endif\n"
|
|
|
|
"gl_FragColor = fog4(col * e_colourident);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultskin",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float3 normal: NORMAL;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float3 light: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
//attribute vec2 v_texcoord;
|
|
//uniform vec3 e_light_dir;
|
|
//uniform vec3 e_light_mul;
|
|
//uniform vec3 e_light_ambient;
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.light = e_light_ambient + (dot(inp.normal,e_light_dir)*e_light_mul);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D shaderTexture[4]; //diffuse, lower, upper, fullbright\n"
|
|
"SamplerState SampleType;\n"
|
|
|
|
//uniform vec4 e_colourident;
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 col;\n"
|
|
"col = shaderTexture[0].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 = shaderTexture[2].Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"float4 lc = shaderTexture[1].Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n"
|
|
"#endif\n"
|
|
"col.rgb *= inp.light;\n"
|
|
"#ifdef FULLBRIGHT\n"
|
|
"float4 fb = shaderTexture[3].Sample(SampleType, inp.tc);\n"
|
|
"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n"
|
|
"#endif\n"
|
|
"return col;\n"
|
|
// return fog4(col * e_colourident);
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "defaultsky",
|
|
//regular sky shader for scrolling q1 skies
|
|
//the sky surfaces are thrown through this as-is.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"varying vec3 pos;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"pos = v_position.xyz;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"uniform float e_time;\n"
|
|
"uniform vec3 e_eyepos;\n"
|
|
"varying vec3 pos;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 tccoord;\n"
|
|
"vec3 dir = pos - e_eyepos;\n"
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"vec4 clouds = texture2D(s_t1, tccoord);\n"
|
|
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D9QUAKE
|
|
{QR_DIRECT3D9, 9, "defaultsky",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"#ifndef FRAGMENT_SHADER\n"
|
|
"float4 pos: POSITION;\n"
|
|
"#endif\n"
|
|
"float3 vpos: TEXCOORD0;\n"
|
|
"};\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"float4x4 m_modelviewprojection;\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
|
|
"outp.vpos = inp.pos;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"float e_time;\n"
|
|
"float3 e_eyepos;\n"
|
|
|
|
"float l_lightradius;\n"
|
|
"float3 l_lightcolour;\n"
|
|
"float3 l_lightposition;\n"
|
|
|
|
"sampler s_diffuse; /*diffuse*/\n"
|
|
"sampler s_fullbright; /*normal*/\n"
|
|
"float4 main (v2f inp) : COLOR0\n"
|
|
"{\n"
|
|
"float2 tccoord;\n"
|
|
|
|
"float3 dir = inp.vpos - e_eyepos;\n"
|
|
|
|
"dir.z *= 3.0;\n"
|
|
"dir.xy /= 0.5*length(dir);\n"
|
|
|
|
"tccoord = (dir.xy + e_time*0.03125);\n"
|
|
"float4 solid = tex2D(s_diffuse, tccoord);\n"
|
|
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"float4 clouds = tex2D(s_fullbright, tccoord);\n"
|
|
|
|
"return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "defaultsky",
|
|
//regular sky shader for scrolling q1 skies
|
|
//the sky surfaces are thrown through this as-is.
|
|
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float3 mpos: TEXCOORD1;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.mpos = outp.pos.xyz;\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D shaderTexture[2];\n"
|
|
"SamplerState SampleType;\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 = shaderTexture[0].Sample(SampleType, tccoord);\n"
|
|
"tccoord = (dir.xy + e_time*0.0625);\n"
|
|
"float4 clouds = shaderTexture[1].Sample(SampleType, tccoord);\n"
|
|
"return (solid*(1.0-clouds.a)) + (clouds.a*clouds);\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 shaderTexture;\n"
|
|
"SamplerState SampleType;\n"
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 tex = shaderTexture.Sample(SampleType, 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"
|
|
"!!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)\n"
|
|
"varying vec3 eyevector;\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)\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"
|
|
"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))\n"
|
|
"vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);\n"
|
|
"#elif defined(SPECULAR) || defined(DELUXE)\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 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 shaderTexture[2];\n"
|
|
"SamplerState SampleType[2];\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 tex = shaderTexture[0].Sample(SampleType[0], inp.tc);\n"
|
|
"float4 lm = shaderTexture[1].Sample(SampleType[1], inp.lmtc);\n"
|
|
|
|
"#ifdef MASK\n"
|
|
"#ifndef MASKOP\n"
|
|
"#define MASKOP >= //drawn if (alpha OP ref) is true.\n"
|
|
"#endif\n"
|
|
//support for alpha masking
|
|
"if (!(tex.a MASKOP MASK))\n"
|
|
"discard;\n"
|
|
"#endif\n"
|
|
|
|
"return tex * lm.bgra;\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;
|
|
// sampler s_t0;
|
|
"Texture2D shaderTexture;\n"
|
|
"SamplerState SampleType;\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 shaderTexture.Sample(SampleType, 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 shaderTexture;\n"
|
|
"SamplerState SampleType;\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"return inp.col * shaderTexture.Sample(SampleType, 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;\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, "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"
|
|
|
|
|
|
"#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"
|
|
|
|
|
|
//texturegather is a gl4 feature, but these shaders are gl2.0 or something
|
|
"#if #include \"cvar/texgather\" && defined(GL_ARB_texture_gather) && defined(PCF) \n"
|
|
"#extension GL_ARB_texture_gather : enable\n"
|
|
"#define DOTEXTUREGATHER\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)\n"
|
|
"varying vec3 eyevector;\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)\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)\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"
|
|
"#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)\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"
|
|
|
|
|
|
"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"
|
|
|
|
"#ifdef DOTEXTUREGATHER\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)\n"
|
|
"vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\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 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 tx_base : register(t0);\n"
|
|
"Texture2D tx_bump : register(t1);\n"
|
|
"Texture2D tx_spec : register(t2);\n"
|
|
"TextureCube tx_cube : register(t3);\n"
|
|
"Texture2D tx_smap : register(t4);\n"
|
|
"Texture2D tx_lower : register(t5);\n"
|
|
"Texture2D tx_upper : register(t6);\n"
|
|
|
|
"SamplerState ss_base : register(s0);\n"
|
|
"SamplerState ss_bump : register(s1);\n"
|
|
"SamplerState ss_spec : register(s2);\n"
|
|
"SamplerState ss_cube : register(s3);\n"
|
|
"SamplerComparisonState ss_smap : register(s4);\n"
|
|
"SamplerState ss_lower : register(s5);\n"
|
|
"SamplerState ss_upper : 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) (tx_smap.Sample(ss_smap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z)
|
|
"#define dosamp(x,y) (tx_smap.SampleCmpLevelZero(ss_smap, 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/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"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float2 tc = inp.tc; //TODO: offsetmapping.\n"
|
|
|
|
"float4 base = tx_base.Sample(ss_base, tc);\n"
|
|
"#ifdef BUMP\n"
|
|
"float4 bump = tx_bump.Sample(ss_bump, tc);\n"
|
|
"bump.rgb = normalize(bump.rgb - 0.5);\n"
|
|
"#else\n"
|
|
"float4 bump = float4(0, 0, 1, 0);\n"
|
|
"#endif\n"
|
|
"float4 spec = tx_spec.Sample(ss_spec, tc);\n"
|
|
"#ifdef CUBE\n"
|
|
"float4 cubemap = tx_cube.Sample(ss_cube, inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
"#ifdef LOWER\n"
|
|
"float4 lower = tx_lower.Sample(ss_lower, tc);\n"
|
|
"base += lower;\n"
|
|
"#endif\n"
|
|
"#ifdef UPPER\n"
|
|
"float4 upper = tx_upper.Sample(ss_upper, tc);\n"
|
|
"base += upper;\n"
|
|
"#endif\n"
|
|
|
|
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"float3 nl = normalize(inp.lightvector);\n"
|
|
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
|
|
"float3 halfdir = normalize(normalize(inp.eyevector) + nl);\n"
|
|
"float specscale = pow(max(dot(halfdir, bump.rgb), 0.0), 32.0 * spec.a);\n"
|
|
|
|
"float4 result;\n"
|
|
"result.a = base.a;\n"
|
|
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
|
|
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
|
|
|
|
"result.rgb *= lightscale * l_colour; //fade light by distance and light colour.\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef PCF\n"
|
|
"result.rgb *= ShadowmapFilter(inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
|
|
//TODO: fog
|
|
"return result;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "underwaterwarp",
|
|
"!!cvarf r_waterwarp\n"
|
|
|
|
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
|
|
//its generally expected to warp the view a little.
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 v_stc;\n"
|
|
"varying vec2 v_warp;\n"
|
|
"varying vec2 v_edge;\n"
|
|
"uniform float e_time;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);\n"
|
|
"v_warp.s = e_time * 0.25 + v_texcoord.s;\n"
|
|
"v_warp.t = e_time * 0.25 + v_texcoord.t;\n"
|
|
"v_edge = v_texcoord.xy;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"varying vec2 v_stc;\n"
|
|
"varying vec2 v_warp;\n"
|
|
"varying vec2 v_edge;\n"
|
|
"uniform sampler2D s_t0;/*$currentrender*/\n"
|
|
"uniform sampler2D s_t1;/*warp image*/\n"
|
|
"uniform sampler2D s_t2;/*edge image*/\n"
|
|
"uniform vec4 e_rendertexturescale;\n"
|
|
"uniform float cvar_r_waterwarp;\n"
|
|
"void main ()\n"
|
|
"{\n"
|
|
"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;\n"
|
|
"vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;\n"
|
|
"vec2 temp = v_stc + offset.xy * amp;\n"
|
|
"gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "menutint",
|
|
"!!cvari r_menutint_inverse\n"
|
|
"!!cvarv r_menutint\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"attribute vec2 v_texcoord;\n"
|
|
"varying vec2 texcoord;\n"
|
|
"uniform vec4 e_rendertexturescale;\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
"texcoord.x = v_texcoord.x*e_rendertexturescale.x;\n"
|
|
"texcoord.y = (1.0-v_texcoord.y)*e_rendertexturescale.y;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
|
|
"varying vec2 texcoord;\n"
|
|
"uniform vec3 cvar_r_menutint;\n"
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform int cvar_r_menutint_inverse;\n"
|
|
"const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\n"
|
|
"const vec3 invertvec = vec3(1.0, 1.0, 1.0);\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
"vec3 texcolor = texture2D(s_t0, texcoord).rgb;\n"
|
|
"float luminance = dot(lumfactors, texcolor);\n"
|
|
"texcolor = vec3(luminance, luminance, luminance);\n"
|
|
"texcolor *= cvar_r_menutint;\n"
|
|
"texcolor = (cvar_r_menutint_inverse > 0) ? (invertvec - texcolor) : texcolor;\n"
|
|
"gl_FragColor = vec4(texcolor, 1.0);\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef GLQUAKE
|
|
{QR_OPENGL, 110, "terrain",
|
|
"!!permu FOG\n"
|
|
"#include \"sys/fog.h\"\n"
|
|
"varying vec2 tc;\n"
|
|
"varying vec2 lm;\n"
|
|
"varying vec4 vc;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"varying vec3 lightvector;\n"
|
|
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
// varying vec3 eyevector;
|
|
// #endif
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"varying vec4 vtexprojcoord;\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"uniform vec3 l_lightposition;\n"
|
|
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
|
// uniform vec3 e_eyepos;
|
|
// #endif
|
|
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
|
"uniform mat4 l_cubematrix;\n"
|
|
"#endif\n"
|
|
"attribute vec3 v_normal;\n"
|
|
"attribute vec3 v_svector;\n"
|
|
"attribute vec3 v_tvector;\n"
|
|
"#endif\n"
|
|
|
|
"attribute vec2 v_texcoord;\n"
|
|
"attribute vec2 v_lmcoord;\n"
|
|
"attribute vec4 v_colour;\n"
|
|
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"tc = v_texcoord.st;\n"
|
|
"lm = v_lmcoord.st;\n"
|
|
"vc = v_colour;\n"
|
|
"gl_Position = ftetransform();\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
//light position is in model space, which is handy.
|
|
"vec3 lightminusvertex = l_lightposition - v_position.xyz;\n"
|
|
|
|
//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes.
|
|
"lightvector = lightminusvertex;\n"
|
|
// lightvector.x = dot(lightminusvertex, v_svector.xyz);
|
|
// lightvector.y = dot(lightminusvertex, v_tvector.xyz);
|
|
// lightvector.z = dot(lightminusvertex, v_normal.xyz);
|
|
|
|
// #if defined(SPECULAR)||defined(OFFSETMAPPING)
|
|
// vec3 eyeminusvertex = e_eyepos - v_position.xyz;
|
|
// eyevector.x = dot(eyeminusvertex, v_svector.xyz);
|
|
// eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
|
|
// eyevector.z = dot(eyeminusvertex, v_normal.xyz);
|
|
// #endif
|
|
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
|
|
//for texture projections/shadowmapping on dlights
|
|
"vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));\n"
|
|
"#endif\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
|
|
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
//four texture passes
|
|
"uniform sampler2D s_t0;\n"
|
|
"uniform sampler2D s_t1;\n"
|
|
"uniform sampler2D s_t2;\n"
|
|
"uniform sampler2D s_t3;\n"
|
|
|
|
//mix values
|
|
"uniform sampler2D s_t4;\n"
|
|
|
|
"#ifdef PCF\n"
|
|
"uniform sampler2DShadow s_t5;\n"
|
|
"#include \"sys/pcf.h\"\n"
|
|
"#endif\n"
|
|
"#ifdef CUBE\n"
|
|
"uniform samplerCube s_t6;\n"
|
|
"#endif\n"
|
|
|
|
//light levels
|
|
"uniform vec4 e_lmscale;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"uniform float l_lightradius;\n"
|
|
"uniform vec3 l_lightcolour;\n"
|
|
"uniform vec3 l_lightcolourscale;\n"
|
|
"#endif\n"
|
|
|
|
"void main (void)\n"
|
|
"{\n"
|
|
"vec4 r;\n"
|
|
"vec4 m = texture2D(s_t4, lm);\n"
|
|
|
|
"r = texture2D(s_t0, tc)*m.r;\n"
|
|
"r += texture2D(s_t1, tc)*m.g;\n"
|
|
"r += texture2D(s_t2, tc)*m.b;\n"
|
|
"r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n"
|
|
|
|
//vertex colours provide a scaler that applies even through rtlights.
|
|
"r *= vc;\n"
|
|
|
|
"#ifdef RTLIGHT\n"
|
|
"vec3 nl = normalize(lightvector);\n"
|
|
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"vec3 diff;\n"
|
|
// #ifdef BUMP
|
|
// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
|
|
// #else
|
|
"colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
|
|
// #endif
|
|
|
|
// #ifdef SPECULAR
|
|
// vec3 halfdir = normalize(normalize(eyevector) + nl);
|
|
// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);
|
|
// diff += l_lightcolourscale.z * spec * specs.rgb;
|
|
// #endif
|
|
|
|
|
|
|
|
"#if defined(SPOT)\n"
|
|
"if (vtexprojcoord.w < 0.0) discard;\n"
|
|
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n"
|
|
"colorscale *= 1.0-(dot(spot,spot));\n"
|
|
"#endif\n"
|
|
"#ifdef PCF\n"
|
|
"colorscale *= ShadowmapFilter(s_t5);\n"
|
|
"#endif\n"
|
|
|
|
"r.rgb *= colorscale * l_lightcolour;\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;\n"
|
|
"#endif\n"
|
|
|
|
"gl_FragColor = fog4additive(r);\n"
|
|
"#else\n"
|
|
//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
|
|
"r *= e_lmscale*vec4(m.aaa,1.0);\n"
|
|
"gl_FragColor = fog4(r);\n"
|
|
"#endif\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|
|
#ifdef D3D11QUAKE
|
|
{QR_DIRECT3D11, 11, "terrain",
|
|
"struct a2v\n"
|
|
"{\n"
|
|
"float4 pos: POSITION;\n"
|
|
"float4 tc: TEXCOORD0;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"};\n"
|
|
"struct v2f\n"
|
|
"{\n"
|
|
"float4 pos: SV_POSITION;\n"
|
|
"float2 tc: TEXCOORD0;\n"
|
|
"float2 lmtc: TEXCOORD1;\n"
|
|
"float4 vcol: COLOR0;\n"
|
|
"float3 vtexprojcoord: TEXCOORD2;\n"
|
|
"float3 vtexprojcoord: TEXCOORD2;\n"
|
|
"};\n"
|
|
|
|
"#include <ftedefs.h>\n"
|
|
|
|
"#ifdef VERTEX_SHADER\n"
|
|
"v2f main (a2v inp)\n"
|
|
"{\n"
|
|
"v2f outp;\n"
|
|
"outp.pos = mul(m_model, inp.pos);\n"
|
|
"outp.pos = mul(m_view, outp.pos);\n"
|
|
"outp.pos = mul(m_projection, outp.pos);\n"
|
|
"outp.tc = inp.tc.xy;\n"
|
|
"outp.lmtc = inp.tc.zw;\n"
|
|
"outp.vcol = inp.vcol;\n"
|
|
"return outp;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
|
|
"#ifdef FRAGMENT_SHADER\n"
|
|
"Texture2D shaderTexture[7];\n"
|
|
"SamplerState SampleType[7];\n"
|
|
|
|
"float4 main (v2f inp) : SV_TARGET\n"
|
|
"{\n"
|
|
"float4 result;\n"
|
|
|
|
"float4 base = shaderTexture[0].Sample(SampleType[0], inp.tc);\n"
|
|
"#ifdef BUMP\n"
|
|
"float4 bump = shaderTexture[1].Sample(SampleType[1], inp.tc);\n"
|
|
"#else\n"
|
|
"float4 bump = float4(0, 0, 1, 0);\n"
|
|
"#endif\n"
|
|
"float4 spec = shaderTexture[2].Sample(SampleType[2], inp.tc);\n"
|
|
"#ifdef CUBE\n"
|
|
"float4 cubemap = shaderTexture[3].Sample(SampleType[3], inp.vtexprojcoord);\n"
|
|
"#endif\n"
|
|
//shadowmap 2d
|
|
"#ifdef LOWER\n"
|
|
"float4 lower = shaderTexture[5].Sample(SampleType[5], inp.tc);\n"
|
|
"base += lower;\n"
|
|
"#endif\n"
|
|
"#ifdef UPPER\n"
|
|
"float4 upper = shaderTexture[6].Sample(SampleType[6], inp.tc);\n"
|
|
"base += upper;\n"
|
|
"#endif\n"
|
|
|
|
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
|
"float3 nl = normalize(inp.lightvector);\n"
|
|
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
|
|
"float3 halfdir = normalize(normalize(eyevector) + nl);\n"
|
|
"float specscale = pow(max(dot(halfdir, bumps), 0.0), 32.0 * spec.a);\n"
|
|
|
|
"result.a = base.a;\n"
|
|
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
|
|
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
|
|
|
|
"result.rgb *= lightscale; //fade light by distance\n"
|
|
|
|
"#ifdef CUBE\n"
|
|
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
|
|
"#endif\n"
|
|
|
|
"return result;\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
},
|
|
#endif
|