1
0
Fork 0
forked from fte/fteqw
fteqw/engine/gl/r_bishaders.h

2621 lines
70 KiB
C
Raw Normal View History

/*
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"
qc: qc temp-strings are now garbage collected. this makes strzone redundant. net: revert the player angles inversion thing from last build. hack some angles. gonna need to tweak the protocol. net: cl_lerp_players is smoother, and defaulted. lets see how many people complain. cl: fix juddering with chase_active+prediction. cl: download progress where the total size is not known now displays something more sane. cl: fixed some issues with rawinput keyboards. cl: added autoupdate option to the menu. cl: autoupdate defaults to a new 'tested' set of builds, instead of the completely untested svn builds. cl: added 'borderless windowed' option to the menus. works on windows. cl: saved games save a preview screenshot. cl: fix some memory leaks on shutdown. cl: added 'setrenderer random' option, might be useful for modders in that it helps highlight bugs/differences between renderers... qc: r_showbboxes now displays the fields of the various entities. tweaked entity lighting to overbright more gracefully. gl: fixed crepuscular lighting. qcc: added % operator. qcc: added inline keyword. qcc: some fixes for accessors. qccgui: now prompts for exe+basedir. sv: added sv_specprint, ala mvdsv. sv: stats now sent over the unreliable channel instead of the reliable one. this allows them to change more frequently. sv: rewrote speedcheat detection. clients will be throttled instead of kicked. unresponsive clients will be simulated instead of freezing in mid-air. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4829 fc73d0e0-1445-4013-8a0c-d673dee63da5
2015-01-21 18:18:37 +00:00
"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"
qc: qc temp-strings are now garbage collected. this makes strzone redundant. net: revert the player angles inversion thing from last build. hack some angles. gonna need to tweak the protocol. net: cl_lerp_players is smoother, and defaulted. lets see how many people complain. cl: fix juddering with chase_active+prediction. cl: download progress where the total size is not known now displays something more sane. cl: fixed some issues with rawinput keyboards. cl: added autoupdate option to the menu. cl: autoupdate defaults to a new 'tested' set of builds, instead of the completely untested svn builds. cl: added 'borderless windowed' option to the menus. works on windows. cl: saved games save a preview screenshot. cl: fix some memory leaks on shutdown. cl: added 'setrenderer random' option, might be useful for modders in that it helps highlight bugs/differences between renderers... qc: r_showbboxes now displays the fields of the various entities. tweaked entity lighting to overbright more gracefully. gl: fixed crepuscular lighting. qcc: added % operator. qcc: added inline keyword. qcc: some fixes for accessors. qccgui: now prompts for exe+basedir. sv: added sv_specprint, ala mvdsv. sv: stats now sent over the unreliable channel instead of the reliable one. this allows them to change more frequently. sv: rewrote speedcheat detection. clients will be throttled instead of kicked. unresponsive clients will be simulated instead of freezing in mid-air. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4829 fc73d0e0-1445-4013-8a0c-d673dee63da5
2015-01-21 18:18:37 +00:00
"gl_FragColor = vec4(0.0,0.0,0.0,0.0);\n"
"for(int i=0; i < NUM_SAMPLES ; i++)\n"
"{\n"
"textCoo -= deltaTextCoord;\n"
"vec4 sample = texture2D(s_t0, textCoo);\n"
"sample *= illuminationDecay * crep_weight;\n"
"gl_FragColor += sample;\n"
"illuminationDecay *= crep_decay;\n"
"}\n"
"gl_FragColor *= vec4(l_lightcolour, 1.0);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "crepuscular_sky",
//pretty much a regular sky shader
//though in reality we should render a sun circle in the middle.
//still, its kinda cool to have scrolling clouds masking out parts of the sun.
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"void main ()\n"
"{\n"
"pos = v_position.xyz;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main ()\n"
"{\n"
"vec2 tccoord;\n"
"vec3 dir = pos - e_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"vec4 clouds = texture2D(s_t1, tccoord);\n"
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "depthonly",
"!!permu FRAMEBLEND\n"
"!!permu SKELETAL\n"
//standard shader used for drawing shadowmap depth.
//also used for masking off portals and other things that want depth and no colour.
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
//the vertex shader is responsible for calculating lighting values.
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"void main ()\n"
"{\n"
"gl_Position = skeletaltransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"void main ()\n"
"{\n"
//must always draw something, supposedly. It might as well be black.
"gl_FragColor = vec4(0, 0, 0, 1);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "depthonly",
//used for generating shadowmaps and stuff that draws nothing.
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"};\n"
"struct v2f\n"
"{\n"
"float3 col: TEXCOORD;\n"
"float4 pos: SV_POSITION;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.col = inp.pos.xyz - l_lightposition;\n"
"return outp;\n"
"}\n"
"#endif\n"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
"#ifdef FRAGMENT_SHADER\n"
"#if LEVEL < 0x10000\n"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
//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"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
"#else\n"
//but on 10, it'll write depth automatically and we don't care about colour.
"void main (v2f inp)\n"
"{\n"
"}\n"
"#endif\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "default2d",
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.
//its really not meant to do anything special.
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"vec4 f = vc;\n"
"#ifdef PREMUL\n"
"f.rgb *= f.a;\n"
"#endif\n"
"f *= texture2D(s_t0, tc);\n"
"gl_FragColor = f;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "default2d",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_projection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_t0;\n"
"SamplerState s_t0;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return t_t0.Sample(s_t0, inp.tc) * inp.vcol;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultadditivesprite",
"!!permu FOG\n"
//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing.
//includes fog, apparently.
"#include \"sys/fog.h\"\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
"void main ()\n"
"{\n"
"gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultskin",
"!!permu FULLBRIGHT\n"
"!!permu UPPERLOWER\n"
"!!permu FRAMEBLEND\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
"!!permu BUMP\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
"#include \"sys/defs.h\"\n"
//standard shader used for models.
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
//the vertex shader is responsible for calculating lighting values.
"varying vec2 tc;\n"
"varying vec3 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"void main ()\n"
"{\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n"
"vec3 n, s, t, w;\n"
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
"#else\n"
"vec3 n;\n"
"gl_Position = skeletaltransform_n(n);\n"
"#endif\n"
"float d = dot(n,e_light_dir);\n"
"if (d < 0.0) //vertex shader. this might get ugly, but I don't really want to make it per vertex.\n"
"d = 0.0; //this avoids the dark side going below the ambient level.\n"
"light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
"tc = v_texcoord;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#include \"sys/fog.h\"\n"
"#if defined(SPECULAR)\n"
"uniform float cvar_gl_specular;\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
"#endif\n"
"void main ()\n"
"{\n"
"vec4 col, sp;\n"
"#ifdef OFFSETMAPPING\n"
"vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);\n"
"#define tc tcoffsetmap\n"
"#endif\n"
"col = texture2D(s_diffuse, tc);\n"
"#ifdef UPPER\n"
"vec4 uc = texture2D(s_upper, tc);\n"
"col.rgb += uc.rgb*e_uppercolour*uc.a;\n"
"#endif\n"
"#ifdef LOWER\n"
"vec4 lc = texture2D(s_lower, tc);\n"
"col.rgb += lc.rgb*e_lowercolour*lc.a;\n"
"#endif\n"
"#if defined(BUMP) && defined(SPECULAR)\n"
"vec3 bumps = normalize(vec3(texture2D(s_normalmap, tc)) - 0.5);\n"
"vec4 specs = texture2D(s_specular, tc);\n"
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0));\n"
"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n"
"col.rgb += cvar_gl_specular * spec * specs.rgb;\n"
"#endif\n"
"col.rgb *= light;\n"
"#ifdef FULLBRIGHT\n"
"vec4 fb = texture2D(s_fullbright, tc);\n"
// col.rgb = mix(col.rgb, fb.rgb, fb.a);
"col.rgb += fb.rgb * fb.a;\n"
"#endif\n"
"gl_FragColor = fog4(col * e_colourident);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultskin",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float3 normal: NORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float3 light: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
//attribute vec2 v_texcoord;
//uniform vec3 e_light_dir;
//uniform vec3 e_light_mul;
//uniform vec3 e_light_ambient;
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.light = e_light_ambient + (dot(inp.normal,e_light_dir)*e_light_mul);\n"
"outp.tc = inp.tc.xy;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_diffuse : register(t0);\n"
"#ifdef UPPER\n"
"Texture2D t_upper : register(t1);\n"
"Texture2D t_lower : register(t2);\n"
"Texture2D t_fullbright : register(t3);\n"
"#else\n"
"Texture2D t_fullbright : register(t1);\n"
"#endif\n"
"SamplerState SampleType;\n"
//uniform vec4 e_colourident;
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 col;\n"
"col = t_diffuse.Sample(SampleType, inp.tc);\n"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
"#ifdef MASK\n"
"#ifndef MASKOP\n"
"#define MASKOP >= //drawn if (alpha OP ref) is true.\n"
"#endif\n"
//support for alpha masking
"if (!(col.a MASKOP MASK))\n"
"discard;\n"
"#endif\n"
"#ifdef UPPER\n"
"float4 uc = t_upper.Sample(SampleType, inp.tc);\n"
"col.rgb = lerp(col.rgb, uc.rgb*e_uppercolour, uc.a);\n"
"#endif\n"
"#ifdef LOWER\n"
"float4 lc = t_lower.Sample(SampleType, inp.tc);\n"
"col.rgb = lerp(col.rgb, lc.rgb*e_lowercolour, lc.a);\n"
"#endif\n"
"col.rgb *= inp.light;\n"
//#ifdef FULLBRIGHT
"float4 fb = t_fullbright.Sample(SampleType, inp.tc);\n"
"col.rgb = lerp(col.rgb, fb.rgb, fb.a);\n"
//#endif
"return col;\n"
// return fog4(col * e_colourident);
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsky",
//regular sky shader for scrolling q1 skies
//the sky surfaces are thrown through this as-is.
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"void main ()\n"
"{\n"
"pos = v_position.xyz;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main ()\n"
"{\n"
"vec2 tccoord;\n"
"vec3 dir = pos - e_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"vec4 clouds = texture2D(s_t1, tccoord);\n"
"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultsky",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"};\n"
"struct v2f\n"
"{\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 vpos: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.vpos = inp.pos;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float e_time;\n"
"float3 e_eyepos;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float3 l_lightposition;\n"
"sampler s_diffuse; /*diffuse*/\n"
"sampler s_fullbright; /*normal*/\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float2 tccoord;\n"
"float3 dir = inp.vpos - e_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"float4 solid = tex2D(s_diffuse, tccoord);\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"float4 clouds = tex2D(s_fullbright, tccoord);\n"
"return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultsky",
//regular sky shader for scrolling q1 skies
//the sky surfaces are thrown through this as-is.
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float3 mpos: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.mpos = outp.pos.xyz;\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_diffuse : register(t0);\n"
"Texture2D t_fullbright : register(t1);\n"
"SamplerState s_diffuse : register(s0);\n"
"SamplerState s_fullbright : register(s1);\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float2 tccoord;\n"
"float3 dir = inp.mpos - v_eyepos;\n"
"dir.z *= 3.0;\n"
"dir.xy /= 0.5*length(dir);\n"
"tccoord = (dir.xy + e_time*0.03125);\n"
"float4 solid = t_diffuse.Sample(s_diffuse, tccoord);\n"
"tccoord = (dir.xy + e_time*0.0625);\n"
"float4 clouds = t_fullbright.Sample(s_fullbright, tccoord);\n"
"return lerp(solid, clouds, clouds.a);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultfill",
"#ifdef VERTEX_SHADER\n"
"attribute vec4 v_colour;\n"
"varying vec4 vc;\n"
"void main ()\n"
"{\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"varying vec4 vc;\n"
"void main ()\n"
"{\n"
"gl_FragColor = vc;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultfill",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_projection, inp.pos);\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return inp.vcol;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultsprite",
"!!permu FOG\n"
//used by both particles and sprites.
//note the fog blending mode is all that differs from defaultadditivesprite
"#include \"sys/fog.h\"\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"uniform vec4 e_colourident;\n"
"void main ()\n"
"{\n"
"vec4 col = texture2D(s_t0, tc);\n"
"#ifdef MASK\n"
"if (col.a < float(MASK))\n"
"discard;\n"
"#endif\n"
"gl_FragColor = fog4blend(col * vc * e_colourident);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultsprite",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_diffuse : register(t0);\n"
"SamplerState s_diffuse : register(s0);\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 tex = t_diffuse.Sample(s_diffuse, inp.tc);\n"
qc: qc temp-strings are now garbage collected. this makes strzone redundant. net: revert the player angles inversion thing from last build. hack some angles. gonna need to tweak the protocol. net: cl_lerp_players is smoother, and defaulted. lets see how many people complain. cl: fix juddering with chase_active+prediction. cl: download progress where the total size is not known now displays something more sane. cl: fixed some issues with rawinput keyboards. cl: added autoupdate option to the menu. cl: autoupdate defaults to a new 'tested' set of builds, instead of the completely untested svn builds. cl: added 'borderless windowed' option to the menus. works on windows. cl: saved games save a preview screenshot. cl: fix some memory leaks on shutdown. cl: added 'setrenderer random' option, might be useful for modders in that it helps highlight bugs/differences between renderers... qc: r_showbboxes now displays the fields of the various entities. tweaked entity lighting to overbright more gracefully. gl: fixed crepuscular lighting. qcc: added % operator. qcc: added inline keyword. qcc: some fixes for accessors. qccgui: now prompts for exe+basedir. sv: added sv_specprint, ala mvdsv. sv: stats now sent over the unreliable channel instead of the reliable one. this allows them to change more frequently. sv: rewrote speedcheat detection. clients will be throttled instead of kicked. unresponsive clients will be simulated instead of freezing in mid-air. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4829 fc73d0e0-1445-4013-8a0c-d673dee63da5
2015-01-21 18:18:37 +00:00
"#ifdef MASK\n"
"if (tex.a < float(MASK))\n"
"discard;\n"
"#endif\n"
//FIXME: no fog, no colourmod
"return tex * inp.vcol;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultwall",
"!!permu DELUXE\n"
"!!permu FULLBRIGHT\n"
"!!permu FOG\n"
"!!permu LIGHTSTYLED\n"
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
"#include \"sys/defs.h\"\n"
//this is what normally draws all of your walls, even with rtlights disabled
//note that the '286' preset uses drawflat_walls instead.
"#include \"sys/fog.h\"\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"varying mat3 invsurface;\n"
"#endif\n"
"varying vec2 tc;\n"
"#ifdef LIGHTSTYLED\n"
//we could use an offset, but that would still need to be per-surface which would break batches
//fixme: merge attributes?
"varying vec2 lm0, lm1, lm2, lm3;\n"
"#else\n"
"varying vec2 lm0;\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"void main ()\n"
"{\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n"
"eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n"
"eyevector.y = dot(eyeminusvertex, v_tvector.xyz);\n"
"eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"invsurface[0] = v_svector;\n"
"invsurface[1] = v_tvector;\n"
"invsurface[2] = v_normal;\n"
"#endif\n"
"tc = v_texcoord;\n"
"lm0 = v_lmcoord;\n"
"#ifdef LIGHTSTYLED\n"
"lm1 = v_lmcoord2;\n"
"lm2 = v_lmcoord3;\n"
"lm3 = v_lmcoord4;\n"
"#endif\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
//samplers
"#define s_colourmap s_t0\n"
"uniform sampler2D s_colourmap;\n"
"#ifdef SPECULAR\n"
"uniform float cvar_gl_specular;\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
"#endif\n"
"void main ()\n"
"{\n"
//adjust texture coords for offsetmapping
"#ifdef OFFSETMAPPING\n"
"vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);\n"
"#define tc tcoffsetmap\n"
"#endif\n"
"#if defined(EIGHTBIT) && !defined(LIGHTSTYLED)\n"
//optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise.
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
//FIXME: this rounding is likely not correct with respect to software rendering. oh well.
"vec2 lmcoord0 = floor(lm0 * 256.0*8.0)/(256.0*8.0);\n"
"#define lm0 lmcoord0\n"
"#endif\n"
//yay, regular texture!
"gl_FragColor = texture2D(s_diffuse, tc);\n"
"#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))\n"
"vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);\n"
"#elif defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)\n"
"vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.\n"
"#endif\n"
//modulate that by the lightmap(s) including deluxemap(s)
"#ifdef LIGHTSTYLED\n"
"vec3 lightmaps;\n"
"#ifdef DELUXE\n"
"lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxmap0, lm0).rgb-0.5);\n"
"lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxmap1, lm1).rgb-0.5);\n"
"lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxmap2, lm2).rgb-0.5);\n"
"lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxmap3, lm3).rgb-0.5);\n"
"#else\n"
"lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;\n"
"lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;\n"
"lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb;\n"
"lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb;\n"
"#endif\n"
"#else\n"
"vec3 lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;\n"
//modulate by the bumpmap dot light
"#ifdef DELUXE\n"
"vec3 delux = 2.0*(texture2D(s_deluxmap, lm0).rgb-0.5);\n"
"lightmaps *= 1.0 / max(0.25, delux.z); //counter the darkening from deluxmaps\n"
"lightmaps *= dot(norm, delux);\n"
"#endif\n"
"#endif\n"
//add in specular, if applicable.
"#ifdef SPECULAR\n"
"vec4 specs = texture2D(s_specular, tc);\n"
"#ifdef DELUXE\n"
//not lightstyled...
"vec3 halfdir = normalize(normalize(eyevector) + 2.0*(texture2D(s_deluxmap0, lm0).rgb-0.5)); //this norm should be the deluxemap info instead\n"
"#else\n"
"vec3 halfdir = normalize(normalize(eyevector) + vec3(0.0, 0.0, 1.0)); //this norm should be the deluxemap info instead\n"
"#endif\n"
"float spec = pow(max(dot(halfdir, norm), 0.0), 32.0 * specs.a);\n"
"spec *= cvar_gl_specular;\n"
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
//we default to something that is not garish when the light value is directly infront of every single pixel.
//we can justify this difference due to the rtlight editor etc showing the *4.
"gl_FragColor.rgb += spec * specs.rgb;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"vec3 rtc = reflect(-eyevector, norm);\n"
"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n"
"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n"
"gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;\n"
"#endif\n"
"#ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant.\n"
"lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.\n"
"float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated.\n"
"lightmaps -= 1.0 / 128.0; //software rendering appears to round down, so make sure we favour the lower values instead of rounding to the nearest\n"
"gl_FragColor.r = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.r)).r; //do 3 lookups. this is to cope with lit files, would be a waste to not support those.\n"
"gl_FragColor.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly.\n"
"gl_FragColor.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical.\n"
"#else\n"
//now we have our diffuse+specular terms, modulate by lightmap values.
"gl_FragColor.rgb *= lightmaps.rgb;\n"
//add on the fullbright
"#ifdef FULLBRIGHT\n"
"gl_FragColor.rgb += texture2D(s_fullbright, tc).rgb;\n"
"#endif\n"
"#endif\n"
//entity modifiers
"gl_FragColor = gl_FragColor * e_colourident;\n"
//and finally hide it all if we're fogged.
"#ifdef FOG\n"
"gl_FragColor = fog4(gl_FragColor);\n"
"#endif\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultwall",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_lightmap : register(t2);\n"
"SamplerState s_lightmap : register(s2);\n"
"Texture2D t_diffuse : register(s0);\n"
"SamplerState s_diffuse : register(s0);\n"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
"Texture2D t_fullbright : register(s1);\n"
"SamplerState s_fullbright : register(s1);\n"
rewrote ban code, merging bans+nonbans+cuffs+mute+cripple+deaf+lagged+vip. added timeouts. new penalties have no dedicated command. use the addip command for it. maplist command now generates links. implemented skin objects for q3. added a csqc builtin for it. also supports compositing skins. playing demos inside zips/pk3s/paks should now work. bumped default rate cvar. added cl_transfer to attempt to connect to a new server without disconnecting first. rewrote fog command. alpha and mindist arguments are now supported. fog change also happens over a short time period. added new args to the showpic console command. can now create clickable items for touchscreen/absmouse users. fixed menus to properly support right-aligned text. this finally fixes variable-width fonts. rewrote console tab completion suggestions display. now clickable links. strings obtained from qc are now marked as const. this has required quite a few added consts all over the place. probably crappy attempt at adding joypad support to the sdl port. no idea if it works. changed key bind event code. buttons now track which event they should trigger when released, instead of being the same one the whole time. this allows +forward etc clickable buttons on screen. Also simplified modifier keys - they no longer trigger random events when pressing the modifier key itself. Right modifiers can now be bound separately from left modifiers. Right will use left's binding if not otherwise bound. Bind assumes left if there's no prefix. multiplayer->setup->network menu no longer crashes. added rgb colours to the translation view (but not to the colour-changing keys). added modelviewer command to view models. added menu_mods menu to switch mods in a more friendly way. will be shown by default if multiple manifests exist in the binarydir. clamped classic tracer density. scrag particles no longer look quite so buggy. added ifdefs to facilitate a potential winrt port. the engine should now have no extra dependencies, but still needs system code+audio drivers to be written. if it can't set a renderer, it'll now try to use *every* renderer until it finds one that works. added experimental mapcluster server mode (that console command). New maps will be started up as required. rewrote skeletal blending code a bit. added cylinder geomtypes. fix cfg_save writing to the wrong path bug. VFS_CLOSE now returns a boolean. false means there was some sort of fatal error (either crc when reading was bad, or the write got corrupted or something). Typically ignorable, depends how robust you want to be. win32 tls code now supports running as a server. added connect tls://address support, as well as equivalent sv_addport support. exposed basic model loading api to plugins. d3d11 backend now optionally supports tessellation hlsl. no suitable hlsl provided by default. !!tess to enable. attempted to add gamma ramp support for d3d11. added support for shader blobs to speed up load times. r_shaderblobs 1 to enable. almost vital for d3d11. added vid_srgb cvar. shadowless lights are no longer disabled if shadows are not supported. attempt to add support for touchscreens in win7/8. Wrote gimmicky lua support, using lua instead of ssqc. define VM_LUA to enable. updated saved game code. can again load saved games from vanilla-like engines. changed scale clamping. 0.0001 should no longer appear as 1. changed default mintic from 0.03 to 0.013 to match vanilla qw. I don't know why it was at 0.03. probably a typo. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4623 fc73d0e0-1445-4013-8a0c-d673dee63da5
2014-03-30 08:55:06 +00:00
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 result;\n"
"result = t_diffuse.Sample(s_diffuse, inp.tc);\n"
"result.rgb *= t_lightmap.Sample(s_lightmap, inp.lmtc).bgr * e_lmscale[0].rgb;\n"
"float4 fb = t_fullbright.Sample(s_fullbright, inp.tc);\n"
"result.rgb += fb.rgb * fb.a;//lerp(result.rgb, fb.rgb, fb.a);\n"
"return result;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultwarp",
"!!permu FOG\n"
"!!cvarf r_wateralpha\n"
"#include \"sys/defs.h\"\n"
//this is the shader that's responsible for drawing default q1 turbulant water surfaces
//this is expected to be moderately fast.
"#include \"sys/fog.h\"\n"
"varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n"
"void main ()\n"
"{\n"
"tc = v_texcoord.st;\n"
"#ifdef FLOW\n"
"tc.s += e_time * -0.5;\n"
"#endif\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#ifndef ALPHA\n"
"uniform float cvar_r_wateralpha;\n"
"#define USEALPHA cvar_r_wateralpha\n"
"#else\n"
"#define USEALPHA float(ALPHA)\n"
"#endif\n"
"void main ()\n"
"{\n"
"vec2 ntc;\n"
"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n"
"vec3 ts = vec3(texture2D(s_diffuse, ntc));\n"
"gl_FragColor = fog4(vec4(ts, USEALPHA));\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "defaultwarp",
"!!cvarf r_wateralpha\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"float cvar_r_wateralpha;\n"
"float e_time;\n"
"sampler s_diffuse;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float2 ntc;\n"
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
"float3 ts = tex2D(s_diffuse, ntc).xyz;\n"
"return float4(ts, cvar_r_wateralpha);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "defaultwarp",
"!!cvarf r_wateralpha\n"
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
// float cvar_r_wateralpha;
// float e_time;
"SamplerState s_diffuse;\n"
"Texture2D t_diffuse;\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float2 ntc;\n"
"ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n"
"ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n"
"return t_diffuse.Sample(s_diffuse, ntc);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultgammacb",
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
"varying vec2 tc;\n"
"varying vec4 vc;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"void main ()\n"
"{\n"
"gl_FragColor = pow(texture2D(s_t0, tc) * vc.g, vec4(vc.r)) + vc.b;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "drawflat_wall",
"!!cvarv r_floorcolor\n"
"!!cvarv r_wallcolor\n"
"!!permu FOG\n"
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
"#include \"sys/fog.h\"\n"
"varying vec4 col;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec3 v_normal;\n"
"attribute vec2 v_lmcoord;\n"
"varying vec2 lm;\n"
"uniform vec3 cvar_r_wallcolor;\n"
"uniform vec3 cvar_r_floorcolor;\n"
"uniform vec4 e_lmscale;\n"
"void main ()\n"
"{\n"
"col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);\n"
"lm = v_lmcoord;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"varying vec2 lm;\n"
"void main ()\n"
"{\n"
"gl_FragColor = fog4(col * texture2D(s_t0, lm));\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "drawflat_wall",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float3 norm: NORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"float4 col: TEXCOORD2;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"outp.col = ((inp.norm.z<0.73)?float4(0.5, 0.5, 0.5, 1):float4(0.25, 0.25, 0.5, 1));\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_lightmap : register(t0);\n"
"SamplerState s_lightmap : register(s0);\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"return inp.col * t_lightmap.Sample(s_lightmap, inp.lmtc);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "lpp_depthnorm",
"!!permu BUMP\n"
"!!permu SKELETAL\n"
//light pre-pass rendering (defered lighting)
//this is the initial pass, that draws the surface normals and depth to the initial colour buffer
"varying vec3 norm, tang, bitang;\n"
"#if defined(BUMP)\n"
"varying vec2 tc;\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"attribute vec2 v_texcoord;\n"
"void main()\n"
"{\n"
"#if defined(BUMP)\n"
"gl_Position = skeletaltransform_nst(norm, tang, bitang);\n"
"tc = v_texcoord;\n"
"#else\n"
"gl_Position = skeletaltransform_n(norm);\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#if defined(BUMP)\n"
"uniform sampler2D s_t0;\n"
"#endif\n"
"void main()\n"
"{\n"
"vec3 onorm;\n"
"#if defined(BUMP)\n"
"vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0;\n"
"onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm);\n"
"#else\n"
"onorm = norm;\n"
"#endif\n"
"gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "lpp_light",
//this shader is a light shader. ideally drawn with a quad covering the entire region
//the output is contribution from this light (which will be additively blended)
//you can blame Electro for much of the maths in here.
//fixme: no fog
"varying vec4 tf;\n"
"#ifdef VERTEX_SHADER\n"
"void main()\n"
"{\n"
"tf = ftetransform();\n"
"gl_Position = tf;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform vec3 l_lightposition;\n"
"uniform mat4 m_invviewprojection;\n"
"uniform vec3 l_lightcolour;\n"
"uniform float l_lightradius;\n"
"vec3 calcLightWorldPos(vec2 screenPos, float depth)\n"
"{\n"
"vec4 pos;\n"
"pos.x = screenPos.x;\n"
"pos.y = screenPos.y;\n"
"pos.z = depth;\n"
"pos.w = 1.0;\n"
"pos = m_invviewprojection * pos;\n"
"return pos.xyz / pos.w;\n"
"}\n"
"void main ()\n"
"{\n"
"vec3 lightColour = l_lightcolour.rgb;\n"
"float lightIntensity = 1.0;\n"
"float lightAttenuation = l_lightradius; // fixme: just use the light radius for now, use better near/far att math separately once working\n"
"float radiusFar = l_lightradius;\n"
"float radiusNear = l_lightradius*0.5;\n"
"vec2 fc;\n"
"fc = tf.xy / tf.w;\n"
"vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);\n"
"float depth = data.a;\n"
"vec3 norm = data.xyz;\n"
/* calc where the wall that generated this sample came from */
"vec3 worldPos = calcLightWorldPos(fc, depth);\n"
/*calc diffuse lighting term*/
"vec3 lightDir = l_lightposition - worldPos;\n"
"float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0);\n"
"float atten = (radiusFar * zdiff) / (radiusFar - radiusNear);\n"
"atten = pow(atten, 2.0);\n"
"lightDir = normalize(lightDir);\n"
"float nDotL = dot(norm, lightDir) * atten;\n"
"float lightDiffuse = max(0.0, nDotL);\n"
"gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "lpp_wall",
//the final defered lighting pass.
//the lighting values were written to some render target, which is fed into this shader, and now we draw all the wall textures with it.
"varying vec2 tc, lm;\n"
"varying vec4 tf;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"lm = v_lmcoord;\n"
"gl_Position = tf = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"uniform sampler2D s_t2;\n"
"uniform vec4 e_lmscale;\n"
"void main ()\n"
"{\n"
"vec2 nst;\n"
"nst = tf.xy / tf.w;\n"
"nst = (1.0 + nst) / 2.0;\n"
"vec4 l = texture2D(s_t0, nst)*5.0;\n"
"vec4 c = texture2D(s_t1, tc);\n"
"vec3 lmsamp = texture2D(s_t2, lm).rgb*e_lmscale;\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"
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvardf r_glsl_pcf\n"
"#ifndef USE_ARB_SHADOW\n"
//fall back on regular samplers if we must
"#define sampler2DShadow sampler2D\n"
"#endif\n"
//this is the main shader responsible for realtime dlights.
//texture units:
//s0=diffuse, s1=normal, s2=specular, s3=shadowmap
//custom modifiers:
//PCF(shadowmap)
//CUBEPROJ(projected cubemap)
//SPOT(projected circle
//CUBESHADOW
"#ifndef r_glsl_pcf\n"
"#error r_glsl_pcf wasnt defined\n"
"#endif\n"
"#if r_glsl_pcf < 1\n"
"#undef r_glsl_pcf\n"
"#define r_glsl_pcf 9\n"
"#endif\n"
"#if 0 && defined(GL_ARB_texture_gather) && defined(PCF) \n"
"#extension GL_ARB_texture_gather : enable\n"
"#endif\n"
"#ifdef UPPERLOWER\n"
"#define UPPER\n"
"#define LOWER\n"
"#endif\n"
//if there's no vertex normals known, disable some stuff.
//FIXME: this results in dupe permutations.
"#ifdef NOBUMP\n"
"#undef SPECULAR\n"
"#undef BUMP\n"
"#undef OFFSETMAPPING\n"
"#endif\n"
"varying vec2 tcbase;\n"
"varying vec3 lightvector;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"varying mat3 invsurface;\n"
"uniform mat4 m_model;\n"
"#endif\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"varying vec4 vtexprojcoord;\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"uniform mat4 l_cubematrix;\n"
"#endif\n"
"#include \"sys/skeletal.h\"\n"
"uniform vec3 l_lightposition;\n"
"attribute vec2 v_texcoord;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"uniform vec3 e_eyepos;\n"
"#endif\n"
"void main ()\n"
"{\n"
"vec3 n, s, t, w;\n"
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
"tcbase = v_texcoord; //pass the texture coords straight through\n"
"vec3 lightminusvertex = l_lightposition - w.xyz;\n"
"#ifdef NOBUMP\n"
//the only important thing is distance
"lightvector = lightminusvertex;\n"
"#else\n"
//the light direction relative to the surface normal, for bumpmapping.
"lightvector.x = dot(lightminusvertex, s.xyz);\n"
"lightvector.y = dot(lightminusvertex, t.xyz);\n"
"lightvector.z = dot(lightminusvertex, n.xyz);\n"
"#endif\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"vec3 eyeminusvertex = e_eyepos - w.xyz;\n"
"eyevector.x = dot(eyeminusvertex, s.xyz);\n"
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"invsurface[0] = v_svector;\n"
"invsurface[1] = v_tvector;\n"
"invsurface[2] = v_normal;\n"
"#endif\n"
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
//for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#include \"sys/fog.h\"\n"
"uniform sampler2D s_t0; //diffuse\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"uniform sampler2D s_t1; //normalmap\n"
"#endif\n"
"#ifdef SPECULAR\n"
"uniform sampler2D s_t2; //specular\n"
"#endif\n"
"#ifdef CUBE\n"
"uniform samplerCube s_t3; //projected cubemap\n"
"#endif\n"
"#ifdef PCF\n"
"#ifdef CUBESHADOW\n"
"uniform samplerCubeShadow s_t4; //shadowmap\n"
"#else\n"
"#if 0//def GL_ARB_texture_gather\n"
"uniform sampler2D s_t4;\n"
"#else\n"
"uniform sampler2DShadow s_t4;\n"
"#endif\n"
"#endif\n"
"#endif\n"
"#ifdef LOWER\n"
"uniform sampler2D s_t5; //pants colours\n"
"uniform vec3 e_lowercolour;\n"
"#endif\n"
"#ifdef UPPER\n"
"uniform sampler2D s_t6; //shirt colours\n"
"uniform vec3 e_uppercolour;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"uniform sampler2D s_reflectmask;\n"
"uniform samplerCube s_reflectcube;\n"
"#endif\n"
"uniform float l_lightradius;\n"
"uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightcolourscale;\n"
"#ifdef PCF\n"
"uniform vec4 l_shadowmapproj; //light projection matrix info\n"
"uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.\n"
"vec3 ShadowmapCoord(void)\n"
"{\n"
"#ifdef SPOT\n"
//bias it. don't bother figuring out which side or anything, its not needed
//l_projmatrix contains the light's projection matrix so no other magic needed
"return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
//#elif defined(CUBESHADOW)
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
"#else\n"
//figure out which axis to use
//texture is arranged thusly:
//forward left up
//back right down
"vec3 dir = abs(vtexprojcoord.xyz);\n"
//assume z is the major axis (ie: forward from the light)
"vec3 t = vtexprojcoord.xyz;\n"
"float ma = dir.z;\n"
"vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n"
"if (dir.x > ma)\n"
"{\n"
"ma = dir.x;\n"
"t = vtexprojcoord.zyx;\n"
"axis.x = 0.5;\n"
"}\n"
"if (dir.y > ma)\n"
"{\n"
"ma = dir.y;\n"
"t = vtexprojcoord.xzy;\n"
"axis.x = 2.5/3.0;\n"
"}\n"
//if the axis is negative, flip it.
"if (t.z > 0.0)\n"
"{\n"
"axis.y = 1.5/2.0;\n"
"t.z = -t.z;\n"
"}\n"
//we also need to pass the result through the light's projection matrix too
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
//also make sure we're in the right quadrant type thing
"return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
"#endif\n"
"}\n"
"float ShadowmapFilter(void)\n"
"{\n"
"vec3 shadowcoord = ShadowmapCoord();\n"
"#if 0//def GL_ARB_texture_gather\n"
"vec2 ipart, fpart;\n"
"#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n"
"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n"
"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n"
"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n"
"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n"
//we now have 4*4 results, woo
//we can just average them for 1/16th precision, but that's still limited graduations
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
"vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength\n"
"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows\n"
"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n"
"#else\n"
"#ifdef USE_ARB_SHADOW\n"
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
"#else\n"
//this will probably be a bit blocky.
"#define dosamp(x,y) float(texture2D(s_t4, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n"
"#endif\n"
"float s = 0.0;\n"
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
"s += dosamp(0.0, 0.0);\n"
"return s;\n"
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"return s/5.0;\n"
"#else\n"
"s += dosamp(-1.0, -1.0);\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(-1.0, 1.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, -1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"s += dosamp(1.0, 1.0);\n"
"return s/9.0;\n"
"#endif\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n"
"#endif\n"
"void main ()\n"
"{\n"
//read raw texture samples (offsetmapping munges the tex coords first)
"#ifdef OFFSETMAPPING\n"
"vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n"
"#define tcbase tcoffsetmap\n"
"#endif\n"
"vec3 bases = vec3(texture2D(s_t0, tcbase));\n"
"#ifdef UPPER\n"
"vec4 uc = texture2D(s_t6, tcbase);\n"
"bases.rgb += uc.rgb*e_uppercolour*uc.a;\n"
"#endif\n"
"#ifdef LOWER\n"
"vec4 lc = texture2D(s_t5, tcbase);\n"
"bases.rgb += lc.rgb*e_lowercolour*lc.a;\n"
"#endif\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n"
"#elif defined(REFLECTCUBEMASK)\n"
"vec3 bumps = vec3(0.0,0.0,1.0);\n"
"#endif\n"
"#ifdef SPECULAR\n"
"vec4 specs = texture2D(s_t2, tcbase);\n"
"#endif\n"
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
"vec3 diff;\n"
"#ifdef NOBUMP\n"
//surface can only support ambient lighting, even for lights that try to avoid it.
"diff = bases * (l_lightcolourscale.x+l_lightcolourscale.y);\n"
"#else\n"
"vec3 nl = normalize(lightvector);\n"
"#ifdef BUMP\n"
"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));\n"
"#else\n"
//we still do bumpmapping even without bumps to ensure colours are always sane. light.exe does it too.
"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
"#endif\n"
"#endif\n"
"#ifdef SPECULAR\n"
"vec3 halfdir = normalize(normalize(eyevector) + nl);\n"
"float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);\n"
"diff += l_lightcolourscale.z * spec * specs.rgb;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"vec3 rtc = reflect(-eyevector, bumps);\n"
"rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];\n"
"rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;\n"
"diff += texture2D(s_reflectmask, tcbase).rgb * textureCube(s_reflectcube, rtc).rgb;\n"
"#endif\n"
"#ifdef CUBE\n"
/*filter the colour by the cubemap projection*/
"diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;\n"
"#endif\n"
"#if defined(SPOT)\n"
/*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/
"if (vtexprojcoord.w < 0.0) discard;\n"
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));\n"
"#endif\n"
"#ifdef PCF\n"
/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
//diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
"colorscale *= ShadowmapFilter();\n"
// diff = ShadowmapCoord();
"#endif\n"
"#if defined(PROJECTION)\n"
/*2d projection, not used*/
// diff *= texture2d(s_t3, shadowcoord);
"#endif\n"
"gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D9QUAKE
{QR_DIRECT3D9, 9, "rtlight",
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!permu OFFSETMAPPING\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
// texture units:
// s0=diffuse, s1=normal, s2=specular, s3=shadowmap
// custom modifiers:
// PCF(shadowmap)
// CUBE(projected cubemap)
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float3 tc: TEXCOORD0;\n"
"float3 n: NORMAL0;\n"
"float3 s: TANGENT0;\n"
"float3 t: BINORMAL0;\n"
"};\n"
"struct v2f\n"
"{\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 tc: TEXCOORD0;\n"
"float3 lpos: TEXCOORD1;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"float3 l_lightposition;\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_modelviewprojection, inp.pos);\n"
"outp.tc = inp.tc;\n"
"float3 lightminusvertex = l_lightposition - inp.pos.xyz;\n"
"outp.lpos.x = dot(lightminusvertex, inp.s.xyz);\n"
"outp.lpos.y = dot(lightminusvertex, inp.t.xyz);\n"
"outp.lpos.z = dot(lightminusvertex, inp.n.xyz);\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"sampler s_diffuse;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
"float3 col = l_lightcolour;\n"
"col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0);\n"
"float3 diff = tex2D(s_diffuse, inp.tc);\n"
"return float4(diff * col, 1);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "rtlight",
"!!permu BUMP\n"
"!!permu FRAMEBLEND\n"
"!!permu SKELETAL\n"
"!!permu UPPERLOWER\n"
"!!permu FOG\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvardf r_glsl_pcf\n"
//this is the main shader responsible for realtime dlights.
//texture units:
//s0=diffuse, s1=normal, s2=specular, s3=shadowmap
//custom modifiers:
//PCF(shadowmap)
//CUBEPROJ(projected cubemap)
//SPOT(projected circle
//CUBESHADOW
"#undef CUBE //engine cannot load cubemaps properly with d3d yet.\n"
"#ifndef r_glsl_pcf\n"
"#error r_glsl_pcf wasn't defined\n"
"#endif\n"
"#if r_glsl_pcf < 1\n"
"#undef r_glsl_pcf\n"
"#define r_glsl_pcf 9\n"
"#endif\n"
"#ifdef UPPERLOWER\n"
"#define UPPER\n"
"#define LOWER\n"
"#endif\n"
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float3 n: NORMAL;\n"
"float3 s: TANGENT;\n"
"float3 t: BINORMAL;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float3 lightvector: TEXCOORD1;\n"
"float3 eyevector: TEXCOORD2;\n"
"float3 vtexprojcoord: TEXCOORD3;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"float4 wpos;\n"
"wpos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, wpos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"float3 lightminusvertex = l_lightposition - wpos.xyz;\n"
"outp.lightvector.x = -dot(lightminusvertex, inp.s.xyz);\n"
"outp.lightvector.y = dot(lightminusvertex, inp.t.xyz);\n"
"outp.lightvector.z = dot(lightminusvertex, inp.n.xyz);\n"
"float3 eyeminusvertex = e_eyepos - wpos.xyz;\n"
"outp.eyevector.x = -dot(eyeminusvertex, inp.s.xyz);\n"
"outp.eyevector.y = dot(eyeminusvertex, inp.t.xyz);\n"
"outp.eyevector.z = dot(eyeminusvertex, inp.n.xyz);\n"
"outp.vtexprojcoord = mul(l_cubematrix, wpos).xyz;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D t_diffuse : register(t0);\n"
"Texture2D t_normalmap : register(t1);\n"
"Texture2D t_specular : register(t2);\n"
"Texture2D t_upper : register(t3);\n"
"Texture2D t_lower : register(t4);\n"
"Texture2D t_shadowmap : register(t5);\n"
"TextureCube t_projectionmap : register(t6);\n"
"SamplerState s_diffuse : register(s0);\n"
"SamplerState s_normalmap : register(s1);\n"
"SamplerState s_specular : register(s2);\n"
"SamplerState s_upper : register(s3);\n"
"SamplerState s_lower : register(s4);\n"
"SamplerComparisonState s_shadowmap : register(s5);\n"
"SamplerState s_projectionmap : register(s6);\n"
"#ifdef PCF\n"
"float3 ShadowmapCoord(float3 vtexprojcoord)\n"
"{\n"
"#ifdef SPOT\n"
//bias it. don't bother figuring out which side or anything, its not needed
//l_projmatrix contains the light's projection matrix so no other magic needed
"vtexprojcoord.z -= 0.015;\n"
"return (vtexprojcoord.xyz + float3(1.0, 1.0, 1.0)) * float3(0.5, 0.5, 0.5);\n"
//#elif defined(CUBESHADOW)
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
"#else\n"
//figure out which axis to use
//texture is arranged thusly:
//forward left up
//back right down
"float3 dir = abs(vtexprojcoord.xyz);\n"
//assume z is the major axis (ie: forward from the light)
"float3 t = vtexprojcoord.xyz;\n"
"float ma = dir.z;\n"
"float3 axis = float3(0.5/3.0, 0.5/2.0, 0.5);\n"
"if (dir.x > ma)\n"
"{\n"
"ma = dir.x;\n"
"t = vtexprojcoord.zyx;\n"
"axis.x = 0.5;\n"
"}\n"
"if (dir.y > ma)\n"
"{\n"
"ma = dir.y;\n"
"t = vtexprojcoord.xzy;\n"
"axis.x = 2.5/3.0;\n"
"}\n"
//if the axis is negative, flip it.
"if (t.z > 0.0)\n"
"{\n"
"axis.y = 1.5/2.0;\n"
"t.z = -t.z;\n"
"}\n"
//we also need to pass the result through the light's projection matrix too
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
//also make sure we're in the right quadrant type thing
"return axis + ((l_shadowmapproj.xyz*t.xyz + float3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
"#endif\n"
"}\n"
"float ShadowmapFilter(float3 vtexprojcoord)\n"
"{\n"
"float3 shadowcoord = ShadowmapCoord(vtexprojcoord);\n"
// #define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r
// #define dosamp(x,y) (t_shadowmap.Sample(s_shadowmap, shadowcoord.xy + (float2(x,y)*l_shadowmapscale.xy)).r < shadowcoord.z)
"#define dosamp(x,y) (t_shadowmap.SampleCmpLevelZero(s_shadowmap, shadowcoord.xy+(float2(x,y)*l_shadowmapscale.xy), shadowcoord.z))\n"
"float s = 0.0;\n"
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
"s += dosamp(0.0, 0.0);\n"
"return s;\n"
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"return s * (1.0/5.0);\n"
"#else\n"
"s += dosamp(-1.0, -1.0);\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(-1.0, 1.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, -1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"s += dosamp(1.0, 1.0);\n"
"return s * (1.0/9.0);\n"
"#endif\n"
"}\n"
"#endif\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float2 tc = inp.tc; //TODO: offsetmapping.\n"
"float4 base = t_diffuse.Sample(s_diffuse, tc);\n"
"#ifdef BUMP\n"
"float4 bump = t_normalmap.Sample(s_normalmap, tc);\n"
"bump.rgb = normalize(bump.rgb - 0.5);\n"
"#else\n"
"float4 bump = float4(0, 0, 1, 0);\n"
"#endif\n"
"float4 spec = t_specular.Sample(s_specular, tc);\n"
"#ifdef CUBE\n"
"float4 cubemap = t_projectionmap.Sample(s_projectionmap, inp.vtexprojcoord);\n"
"#endif\n"
"#ifdef LOWER\n"
"float4 lower = t_lower.Sample(s_lower, tc);\n"
"base += lower;\n"
"#endif\n"
"#ifdef UPPER\n"
"float4 upper = t_upper.Sample(s_upper, tc);\n"
"base += upper;\n"
"#endif\n"
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
"float3 nl = normalize(inp.lightvector);\n"
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
"float3 halfdir = normalize(normalize(inp.eyevector) + nl);\n"
"float specscale = pow(max(dot(halfdir, bump.rgb), 0.0), 32.0 * spec.a);\n"
"float4 result;\n"
"result.a = base.a;\n"
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
"result.rgb *= lightscale * l_colour; //fade light by distance and light colour.\n"
"#ifdef CUBE\n"
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
"#endif\n"
"#ifdef PCF\n"
"result.rgb *= ShadowmapFilter(inp.vtexprojcoord);\n"
"#endif\n"
//TODO: fog
"return result;\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "underwaterwarp",
"!!cvarf r_waterwarp\n"
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
//its generally expected to warp the view a little.
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"uniform float e_time;\n"
"void main ()\n"
"{\n"
"gl_Position = ftetransform();\n"
"v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);\n"
"v_warp.s = e_time * 0.25 + v_texcoord.s;\n"
"v_warp.t = e_time * 0.25 + v_texcoord.t;\n"
"v_edge = v_texcoord.xy;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"uniform sampler2D s_t0;/*$currentrender*/\n"
"uniform sampler2D s_t1;/*warp image*/\n"
"uniform sampler2D s_t2;/*edge image*/\n"
"uniform vec4 e_rendertexturescale;\n"
"uniform float cvar_r_waterwarp;\n"
"void main ()\n"
"{\n"
"vec2 amp = (0.010 / 0.625) * cvar_r_waterwarp * texture2D(s_t2, v_edge).rg;\n"
"vec3 offset = (texture2D(s_t1, v_warp).rgb - 0.5) * 2.0;\n"
"vec2 temp = v_stc + offset.xy * amp;\n"
"gl_FragColor = texture2D(s_t0, temp*e_rendertexturescale.st);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "menutint",
"!!cvari r_menutint_inverse\n"
"!!cvarv r_menutint\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 texcoord;\n"
"uniform vec4 e_rendertexturescale;\n"
"void main(void)\n"
"{\n"
"texcoord.x = v_texcoord.x*e_rendertexturescale.x;\n"
"texcoord.y = (1.0-v_texcoord.y)*e_rendertexturescale.y;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 texcoord;\n"
"uniform vec3 cvar_r_menutint;\n"
"uniform sampler2D s_t0;\n"
"uniform int cvar_r_menutint_inverse;\n"
"const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\n"
"const vec3 invertvec = vec3(1.0, 1.0, 1.0);\n"
"void main(void)\n"
"{\n"
"vec3 texcolor = texture2D(s_t0, texcoord).rgb;\n"
"float luminance = dot(lumfactors, texcolor);\n"
"texcolor = vec3(luminance, luminance, luminance);\n"
"texcolor *= cvar_r_menutint;\n"
"texcolor = (cvar_r_menutint_inverse > 0) ? (invertvec - texcolor) : texcolor;\n"
"gl_FragColor = vec4(texcolor, 1.0);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "terrain",
"!!permu FOG\n"
"#include \"sys/fog.h\"\n"
"varying vec2 tc;\n"
"varying vec2 lm;\n"
"varying vec4 vc;\n"
"#ifdef RTLIGHT\n"
"varying vec3 lightvector;\n"
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
// varying vec3 eyevector;
// #endif
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"varying vec4 vtexprojcoord;\n"
"#endif\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#ifdef RTLIGHT\n"
"uniform vec3 l_lightposition;\n"
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
// uniform vec3 e_eyepos;
// #endif
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"uniform mat4 l_cubematrix;\n"
"#endif\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"#endif\n"
"attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n"
"attribute vec4 v_colour;\n"
"void main (void)\n"
"{\n"
"tc = v_texcoord.st;\n"
"lm = v_lmcoord.st;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"#ifdef RTLIGHT\n"
//light position is in model space, which is handy.
"vec3 lightminusvertex = l_lightposition - v_position.xyz;\n"
//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes.
"lightvector = lightminusvertex;\n"
// lightvector.x = dot(lightminusvertex, v_svector.xyz);
// lightvector.y = dot(lightminusvertex, v_tvector.xyz);
// lightvector.z = dot(lightminusvertex, v_normal.xyz);
// #if defined(SPECULAR)||defined(OFFSETMAPPING)
// vec3 eyeminusvertex = e_eyepos - v_position.xyz;
// eyevector.x = dot(eyeminusvertex, v_svector.xyz);
// eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
// eyevector.z = dot(eyeminusvertex, v_normal.xyz);
// #endif
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
//for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));\n"
"#endif\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
//four texture passes
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"uniform sampler2D s_t2;\n"
"uniform sampler2D s_t3;\n"
//mix values
"uniform sampler2D s_t4;\n"
"#ifdef PCF\n"
"uniform sampler2DShadow s_t5;\n"
"#include \"sys/pcf.h\"\n"
"#endif\n"
"#ifdef CUBE\n"
"uniform samplerCube s_t6;\n"
"#endif\n"
//light levels
"uniform vec4 e_lmscale;\n"
"#ifdef RTLIGHT\n"
"uniform float l_lightradius;\n"
"uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightcolourscale;\n"
"#endif\n"
"void main (void)\n"
"{\n"
"vec4 r;\n"
"vec4 m = texture2D(s_t4, lm);\n"
"r = texture2D(s_t0, tc)*m.r;\n"
"r += texture2D(s_t1, tc)*m.g;\n"
"r += texture2D(s_t2, tc)*m.b;\n"
"r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n"
//vertex colours provide a scaler that applies even through rtlights.
"r *= vc;\n"
"#ifdef RTLIGHT\n"
"vec3 nl = normalize(lightvector);\n"
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
"vec3 diff;\n"
// #ifdef BUMP
// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
// #else
"colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
// #endif
// #ifdef SPECULAR
// vec3 halfdir = normalize(normalize(eyevector) + nl);
// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);
// diff += l_lightcolourscale.z * spec * specs.rgb;
// #endif
"#if defined(SPOT)\n"
"if (vtexprojcoord.w < 0.0) discard;\n"
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n"
"colorscale *= 1.0-(dot(spot,spot));\n"
"#endif\n"
"#ifdef PCF\n"
"colorscale *= ShadowmapFilter(s_t5);\n"
"#endif\n"
"r.rgb *= colorscale * l_lightcolour;\n"
"#ifdef CUBE\n"
"r.rgb *= textureCube(s_t6, vtexprojcoord.xyz).rgb;\n"
"#endif\n"
"gl_FragColor = fog4additive(r);\n"
"#else\n"
//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
"r *= e_lmscale*vec4(m.aaa,1.0);\n"
"gl_FragColor = fog4(r);\n"
"#endif\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3D11QUAKE
{QR_DIRECT3D11, 11, "terrain",
"struct a2v\n"
"{\n"
"float4 pos: POSITION;\n"
"float4 tc: TEXCOORD0;\n"
"float4 vcol: COLOR0;\n"
"};\n"
"struct v2f\n"
"{\n"
"float4 pos: SV_POSITION;\n"
"float2 tc: TEXCOORD0;\n"
"float2 lmtc: TEXCOORD1;\n"
"float4 vcol: COLOR0;\n"
"float3 vtexprojcoord: TEXCOORD2;\n"
"float3 vtexprojcoord: TEXCOORD2;\n"
"};\n"
"#include <ftedefs.h>\n"
"#ifdef VERTEX_SHADER\n"
"v2f main (a2v inp)\n"
"{\n"
"v2f outp;\n"
"outp.pos = mul(m_model, inp.pos);\n"
"outp.pos = mul(m_view, outp.pos);\n"
"outp.pos = mul(m_projection, outp.pos);\n"
"outp.tc = inp.tc.xy;\n"
"outp.lmtc = inp.tc.zw;\n"
"outp.vcol = inp.vcol;\n"
"return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"Texture2D shaderTexture[7];\n"
"SamplerState SampleType[7];\n"
"float4 main (v2f inp) : SV_TARGET\n"
"{\n"
"float4 result;\n"
"float4 base = shaderTexture[0].Sample(SampleType[0], inp.tc);\n"
"#ifdef BUMP\n"
"float4 bump = shaderTexture[1].Sample(SampleType[1], inp.tc);\n"
"#else\n"
"float4 bump = float4(0, 0, 1, 0);\n"
"#endif\n"
"float4 spec = shaderTexture[2].Sample(SampleType[2], inp.tc);\n"
"#ifdef CUBE\n"
"float4 cubemap = shaderTexture[3].Sample(SampleType[3], inp.vtexprojcoord);\n"
"#endif\n"
//shadowmap 2d
"#ifdef LOWER\n"
"float4 lower = shaderTexture[5].Sample(SampleType[5], inp.tc);\n"
"base += lower;\n"
"#endif\n"
"#ifdef UPPER\n"
"float4 upper = shaderTexture[6].Sample(SampleType[6], inp.tc);\n"
"base += upper;\n"
"#endif\n"
"float lightscale = max(1.0 - (dot(inp.lightvector,inp.lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
"float3 nl = normalize(inp.lightvector);\n"
"float bumpscale = max(dot(bump.xyz, nl), 0.0);\n"
"float3 halfdir = normalize(normalize(eyevector) + nl);\n"
"float specscale = pow(max(dot(halfdir, bumps), 0.0), 32.0 * spec.a);\n"
"result.a = base.a;\n"
"result.rgb = base.rgb * (l_lightcolourscale.x + l_lightcolourscale.y * bumpscale); //amient light + diffuse\n"
"result.rgb += spec.rgb * l_lightcolourscale.z * specscale; //specular\n"
"result.rgb *= lightscale; //fade light by distance\n"
"#ifdef CUBE\n"
"result.rgb *= cubemap.rgb; //fade by cubemap\n"
"#endif\n"
"return result;\n"
"}\n"
"#endif\n"
},
#endif