mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-29 07:02:12 +00:00
811bce25f1
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds. Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system). Add mastervolume cvar (for ss). Add r_shadows 2 (aka fake shadows - for ss). Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss). Better support for some effectinfo hacks (for ss). Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss). Rework the dpcsqc versions of project+unproject builtins for better compat (for ss). Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss). Better compat with DP's loadfont console command (for ss). Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss). Detect dp's m_draw extension, to work around it (for ss). Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss). loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts. Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0. Hackily parse emoji.json to provide 💩 etc suggestions. Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic. screenshot_cubemap will now capture half-float images when saving to ktx or dds files. Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings. Fixed size of gfx/loading.lmp when replacement textures are used. Added mipmap support for rg8 and l8a8 textures. r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones. Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP). Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research. Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates. Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds. Added setmousepos builtin. Should work with glx+win32 build. VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees). Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding). Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW). sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories. edit command now displays end1.bin/end2.bin correctly, because we can. Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant. Fix threading race condition in sha1 lookups. Updated f_ruleset to include the same extra flags reported by ezquake. A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc). fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only. HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written). Fixed buf_cvarlist, should work in xonotic now, and without segfaults. Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though. Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs. sdl: support custom icons. sdl: support choosing a specific display. Added some documentation to menuqc builtins. menusys: use outlines for slightly more readable fonts. menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
423 lines
12 KiB
GLSL
423 lines
12 KiB
GLSL
!!ver 100 450
|
|
!!permu TESS
|
|
!!permu DELUXE
|
|
!!permu FULLBRIGHT
|
|
!!permu FOG
|
|
!!permu LIGHTSTYLED
|
|
!!permu BUMP
|
|
!!permu SPECULAR
|
|
!!permu REFLECTCUBEMASK
|
|
!!permu FAKESHADOWS
|
|
!!cvarf r_glsl_offsetmapping_scale
|
|
!!cvardf r_glsl_pcf
|
|
!!cvardf r_tessellation_level=5
|
|
!!samps diffuse
|
|
!!samps !EIGHTBIT =FULLBRIGHT fullbright
|
|
!!samps !EIGHTBIT =BUMP normalmap
|
|
!!samps !EIGHTBIT =REFLECTCUBEMASK reflectmask reflectcube
|
|
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
|
|
!!samps =EIGHTBIT paletted 1
|
|
!!samps =SPECULAR specular
|
|
!!samps lightmap
|
|
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3
|
|
!!samps =DELUXE deluxmap
|
|
!!samps =LIGHTSTYLED =DELUXE deluxemap1 deluxemap2 deluxemap3
|
|
!!samps =FAKESHADOWS shadowmap
|
|
|
|
#if defined(ORM) || defined(SG)
|
|
#define PBR
|
|
#endif
|
|
|
|
#include "sys/defs.h"
|
|
|
|
//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"
|
|
|
|
#if !defined(TESS_CONTROL_SHADER)
|
|
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
|
|
varying vec3 eyevector;
|
|
#endif
|
|
|
|
#if defined(REFLECTCUBEMASK) || defined(BUMPMODELSPACE)
|
|
varying mat3 invsurface;
|
|
#endif
|
|
|
|
varying vec2 tc;
|
|
#ifdef VERTEXLIT
|
|
varying vec4 vc;
|
|
#else
|
|
#ifdef LIGHTSTYLED
|
|
//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;
|
|
#else
|
|
varying vec2 lm0;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef FAKESHADOWS
|
|
varying vec4 vtexprojcoord;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef VERTEX_SHADER
|
|
#ifdef TESS
|
|
varying vec3 vertex, normal;
|
|
#endif
|
|
void main ()
|
|
{
|
|
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
|
|
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(REFLECTCUBEMASK) || defined(BUMPMODELSPACE)
|
|
invsurface = mat3(v_svector, v_tvector, v_normal);
|
|
#endif
|
|
tc = v_texcoord;
|
|
#ifdef FLOW
|
|
tc.s += e_time * -0.5;
|
|
#endif
|
|
#ifdef VERTEXLIT
|
|
#ifdef LIGHTSTYLED
|
|
//FIXME, only one colour.
|
|
vc = v_colour * e_lmscale[0];
|
|
#else
|
|
vc = v_colour * e_lmscale;
|
|
#endif
|
|
#else
|
|
lm0 = v_lmcoord;
|
|
#ifdef LIGHTSTYLED
|
|
lm1 = v_lmcoord2;
|
|
lm2 = v_lmcoord3;
|
|
lm3 = v_lmcoord4;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef TESS
|
|
vertex = v_position;
|
|
normal = v_normal;
|
|
#endif
|
|
|
|
#ifdef FAKESHADOWS
|
|
gl_Position = ftetransform();
|
|
vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));
|
|
#else
|
|
gl_Position = ftetransform();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(TESS_CONTROL_SHADER)
|
|
layout(vertices = 3) out;
|
|
|
|
in vec3 vertex[];
|
|
out vec3 t_vertex[];
|
|
in vec3 normal[];
|
|
out vec3 t_normal[];
|
|
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
|
|
in vec3 eyevector[];
|
|
out vec3 t_eyevector[];
|
|
#endif
|
|
#ifdef REFLECTCUBEMASK
|
|
in mat3 invsurface[];
|
|
out mat3 t_invsurface[];
|
|
#endif
|
|
in vec2 tc[];
|
|
out vec2 t_tc[];
|
|
#ifdef VERTEXLIT
|
|
in vec4 vc[];
|
|
out vec4 t_vc[];
|
|
#else
|
|
in vec2 lm0[];
|
|
out vec2 t_lm0[];
|
|
#ifdef LIGHTSTYLED
|
|
in vec2 lm1[], lm2[], lm3[];
|
|
out vec2 t_lm1[], t_lm2[], t_lm3[];
|
|
#endif
|
|
#endif
|
|
void main()
|
|
{
|
|
//the control shader needs to pass stuff through
|
|
#define id gl_InvocationID
|
|
t_vertex[id] = vertex[id];
|
|
t_normal[id] = normal[id];
|
|
#ifdef REFLECTCUBEMASK
|
|
t_invsurface[id] = invsurface[id];
|
|
#endif
|
|
t_tc[id] = tc[id];
|
|
#ifdef VERTEXLIT
|
|
t_vc[id] = vc[id];
|
|
#else
|
|
t_lm0[id] = lm0[id];
|
|
#ifdef LIGHTSTYLED
|
|
t_lm1[id] = lm1[id];
|
|
t_lm2[id] = lm2[id];
|
|
t_lm3[id] = lm3[id];
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
|
|
t_eyevector[id] = eyevector[id];
|
|
#endif
|
|
|
|
gl_TessLevelOuter[0] = float(r_tessellation_level);
|
|
gl_TessLevelOuter[1] = float(r_tessellation_level);
|
|
gl_TessLevelOuter[2] = float(r_tessellation_level);
|
|
gl_TessLevelInner[0] = float(r_tessellation_level);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(TESS_EVALUATION_SHADER)
|
|
layout(triangles) in;
|
|
|
|
in vec3 t_vertex[];
|
|
in vec3 t_normal[];
|
|
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
|
|
in vec3 t_eyevector[];
|
|
#endif
|
|
#ifdef REFLECTCUBEMASK
|
|
in mat3 t_invsurface[];
|
|
#endif
|
|
in vec2 t_tc[];
|
|
#ifdef VERTEXLIT
|
|
in vec4 t_vc[];
|
|
#else
|
|
#ifdef LIGHTSTYLED
|
|
//we could use an offset, but that would still need to be per-surface which would break batches
|
|
//fixme: merge attributes?
|
|
in vec2 t_lm0[], t_lm1[], t_lm2[], t_lm3[];
|
|
#else
|
|
in vec2 t_lm0[];
|
|
#endif
|
|
#endif
|
|
|
|
#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])
|
|
void main()
|
|
{
|
|
#define factor 1.0
|
|
tc = LERP(t_tc);
|
|
#ifdef VERTEXLIT
|
|
vc = LERP(t_vc);
|
|
#else
|
|
lm0 = LERP(t_lm0);
|
|
#ifdef LIGHTSTYLED
|
|
lm1 = LERP(t_lm1);
|
|
lm2 = LERP(t_lm2);
|
|
lm3 = LERP(t_lm3);
|
|
#endif
|
|
#endif
|
|
vec3 w = LERP(t_vertex);
|
|
|
|
vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];
|
|
vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];
|
|
vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];
|
|
w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);
|
|
|
|
#if defined(PCF) || defined(SPOT) || defined(CUBE)
|
|
//for texture projections/shadowmapping on dlights
|
|
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
|
|
#endif
|
|
|
|
//FIXME: we should be recalcing these here, instead of just lerping them
|
|
#ifdef REFLECTCUBEMASK
|
|
invsurface = LERP(t_invsurface);
|
|
#endif
|
|
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
|
|
eyevector = LERP(t_eyevector);
|
|
#endif
|
|
|
|
gl_Position = m_modelviewprojection * vec4(w,1.0);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef FRAGMENT_SHADER
|
|
#define s_colourmap s_t0
|
|
|
|
#include "sys/pbr.h"
|
|
#include "sys/pcf.h"
|
|
|
|
#ifdef OFFSETMAPPING
|
|
#include "sys/offsetmapping.h"
|
|
#endif
|
|
void main ()
|
|
{
|
|
//adjust texture coords for offsetmapping
|
|
#ifdef OFFSETMAPPING
|
|
vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);
|
|
#define tc tcoffsetmap
|
|
#endif
|
|
|
|
#if defined(EIGHTBIT) && !defined(LIGHTSTYLED)
|
|
//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.
|
|
#if __VERSION__ >= 130
|
|
vec2 lmsize = vec2(textureSize(s_lightmap0, 0));
|
|
#else
|
|
#define lmsize vec2(128.0,2048.0)
|
|
#endif
|
|
#define texelstolightmap (16.0)
|
|
vec2 lmcoord0 = floor(lm0 * lmsize*texelstolightmap)/(lmsize*texelstolightmap);
|
|
#define lm0 lmcoord0
|
|
#endif
|
|
|
|
|
|
//Read the base texture (with EIGHTBIT only alpha is needed)
|
|
vec4 col = texture2D(s_diffuse, tc);
|
|
|
|
#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))
|
|
vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);
|
|
#elif defined(PBR) || defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)
|
|
vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.
|
|
#endif
|
|
|
|
//modulate that by the lightmap(s) including deluxemap(s)
|
|
#ifdef VERTEXLIT
|
|
#ifdef LIGHTSTYLED
|
|
vec3 lightmaps = vc.rgb;
|
|
#else
|
|
vec3 lightmaps = vc.rgb;
|
|
#endif
|
|
#define deluxe vec3(0.0,0.0,1.0)
|
|
#else
|
|
#ifdef LIGHTSTYLED
|
|
#define deluxe vec3(0.0,0.0,1.0)
|
|
vec3 lightmaps;
|
|
#ifdef DELUXE
|
|
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxemap0, lm0).rgb-0.5);
|
|
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxemap1, lm1).rgb-0.5);
|
|
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxemap2, lm2).rgb-0.5);
|
|
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxemap3, lm3).rgb-0.5);
|
|
#else
|
|
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;
|
|
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;
|
|
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb;
|
|
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb;
|
|
#endif
|
|
#else
|
|
vec3 lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
|
|
//modulate by the bumpmap dot light
|
|
#ifdef DELUXE
|
|
vec3 deluxe = (texture2D(s_deluxemap, lm0).rgb-0.5);
|
|
#ifdef BUMPMODELSPACE
|
|
deluxe = normalize(deluxe*invsurface);
|
|
#else
|
|
deluxe = normalize(deluxe);
|
|
lightmaps *= 2.0 / max(0.25, deluxe.z); //counter the darkening from deluxemaps
|
|
#endif
|
|
lightmaps *= dot(norm, deluxe);
|
|
#else
|
|
#define deluxe vec3(0.0,0.0,1.0)
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
// col *= factor_base;
|
|
#define dielectricSpecular 0.04
|
|
#ifdef SPECULAR
|
|
vec4 specs = texture2D(s_specular, tc);//*factor_spec;
|
|
#ifdef ORM
|
|
#define occlusion specs.r
|
|
#define roughness specs.g
|
|
#define metalness specs.b
|
|
#define gloss (1.0-roughness)
|
|
#define ambientrgb (specrgb+col.rgb)
|
|
vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness);
|
|
col.rgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);
|
|
#elif defined(SG) //pbr-style specular+glossiness
|
|
//occlusion needs to be baked in. :(
|
|
#define roughness (1.0-specs.a)
|
|
#define gloss specs.a
|
|
#define specrgb specs.rgb
|
|
#define ambientrgb (specs.rgb+col.rgb)
|
|
#else //blinn-phong
|
|
#define roughness (1.0-specs.a)
|
|
#define gloss specs.a
|
|
#define specrgb specs.rgb
|
|
#define ambientrgb col.rgb
|
|
#endif
|
|
#else
|
|
#define roughness 0.3
|
|
#define specrgb 1.0 //vec3(dielectricSpecular)
|
|
#endif
|
|
|
|
//add in specular, if applicable.
|
|
#ifdef PBR
|
|
col.rgb = DoPBR(norm, normalize(eyevector), deluxe, roughness, col.rgb, specrgb, vec3(0.0,1.0,1.0));//*e_light_mul + e_light_ambient*.25*ambientrgb;
|
|
#elif defined(gloss)
|
|
vec3 halfdir = normalize(normalize(eyevector) + deluxe); //this norm should be the deluxemap info instead
|
|
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * gloss);
|
|
spec *= FTE_SPECULAR_MULTIPLIER;
|
|
//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.
|
|
col.rgb += spec * specrgb;
|
|
#endif
|
|
|
|
#ifdef REFLECTCUBEMASK
|
|
vec3 rtc = reflect(normalize(-eyevector), norm);
|
|
rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];
|
|
rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;
|
|
col.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;
|
|
#endif
|
|
|
|
#ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant.
|
|
lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.
|
|
float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated.
|
|
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
|
|
col.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.
|
|
col.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly.
|
|
col.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical.
|
|
#else
|
|
//now we have our diffuse+specular terms, modulate by lightmap values.
|
|
col.rgb *= lightmaps.rgb;
|
|
//add on the fullbright
|
|
#ifdef FULLBRIGHT
|
|
col.rgb += texture2D(s_fullbright, tc).rgb;
|
|
#endif
|
|
#endif
|
|
|
|
//entity modifiers
|
|
col *= e_colourident;
|
|
|
|
#ifdef FAKESHADOWS
|
|
/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
|
|
col.rgb *= ShadowmapFilter(s_shadowmap, vtexprojcoord);
|
|
//col.g = ShadowmapFilter(s_shadowmap, vtexprojcoord);
|
|
#endif
|
|
|
|
#if defined(MASK)
|
|
#if defined(MASKLT)
|
|
if (col.a < MASK)
|
|
discard;
|
|
#else
|
|
if (col.a >= MASK)
|
|
discard;
|
|
#endif
|
|
col.a = 1.0; //alpha blending AND alpha testing usually looks stupid, plus it screws up our fog.
|
|
#endif
|
|
|
|
//and finally hide it all if we're fogged.
|
|
gl_FragColor = fog4(col);
|
|
}
|
|
#endif
|
|
|