mirror of
https://github.com/Q3Rally-Team/q3rally.git
synced 2024-11-23 04:12:02 +00:00
96a9e2a9aa
This updates from SDL 2.0.4 to SDL 2.0.8. Fix nullptr dereference in front of nullptr check in FS_CheckPak0 Fix undefined behaviour due to shifting signed in snd_mem.c Fix shifting bits out of byte in tr_font.c Fix shift into sign in cl_cin.c Fix signed bit operations in MSG_ReadBits Add missing address operator in cm_polylib.c OpenGL1: Decay float[8] to float * in tr_marks.c Avoid srcList[-1] in snd_openal.c Fix the behaviour of CVAR_LATCH|CVAR_CHEAT cvars Maximize cURL buffer size Fix mouse grab after toggling fullscreen Fix q3history buffer not cleared between mods and OOB-access Revert "Removed "Color Depth" from q3_ui system settings, it didn't control anything." Fix displayed color/depth/stencil bits values Restore setting r_colorbits in q3_ui Make setting r_stencilbits more consistent in Team Arena UI Fix map list in Team Arena start server menu after entering SP menu Support SDL audio devices that require float32 samples. sdl_snd.c should just initialize SDL audio without checking SDL_WasInit(). There's no need to SDL_PauseAudio(1) before calling SDL_CloseAudio(). Added audio capture support to SDL backend. Use the SDL2 audio device interface instead of the legacy 1.2 API. Disable SDL audio capture until prebuilt SDL libraries are updated to 2.0.8. Update SDL2 to 2.0.8 Add SDL 2.0.1 headers for macOS PPC Make macOS Universal Bundle target 10.6 for x86 and x86_64 Fix possible bot goal state NULL pointer dereference Fix uninitialized bot_goal_t fields Remove unnecessary NULL pointer check in Cmd_RemoveCommand Make UI_DrawProportionalString handle NULL string Fix compiling against macOS system OpenAL and SDL2 frameworks Fix array index in CanDamage() function - discovered by MARTY Fix compiling Makefile (broke in macOS frameworks commit) Fix clearing keys for control in Team Arena UI Make s_useOpenAL be CVAR_LATCH Improvements for dedicated camera followers (team follow1/2) Fix not closing description.txt and fix path seperator Fix duplicate bots displayed in Team Arena ingame add bot menu OpenGL2: Fix parsing specularScale in shaders Don't allow SDL audio capture using pulseaudio Isolate the Altivec code so non-Altivec PPC targets can use the same binary. Limit -maltivec to specific source files on OpenBSD too (untested) Use SDL 2.0.1 headers for macOS ppc64 Fix console offset while Team Arena voiceMenu is open OpenGL2: Readd r_deluxeSpecular. Fix client kicked as unpure when missing the latest cgame/ui pk3s Don't create multiple windows when GL context creation fails Require OpenGL 1.2 for GL_CLAMP_TO_EDGE Fix Linux uninstaller requiring Bash Fix Linux uninstaller redirecting stderr to stdout in preuninstall.sh Reported by @illwieckz. Fix in_restart causing fatal error while video is shutdown Allow pkg-config binary to be overridden with PKG_CONFIG Make testgun command without argument disable test gun model Remove unused renderer_buffer variable Don't upload 8 bit grayscale images as 16 bit luminance OpenGL1: Use RE_UploadCinematic() instead of duplicate code Don't load non-core GL functions for OpenGL 3.2 core context Load OpenGL ES 2.0 function procs Don't check fixed function GL extensions when using shader pipeline OpenGL2: Fix world VAO cache drawing when glIndex_t is unsigned short OpenGL2: Misc fixes and cleanup Fix IQM root joint backlerp when joint number is more than 0 Improve IQM loading Improve IQM CPU vertex skinning performance OpenGL2: Add GPU vertex skinning for IQM models
440 lines
11 KiB
GLSL
440 lines
11 KiB
GLSL
uniform sampler2D u_DiffuseMap;
|
|
|
|
#if defined(USE_LIGHTMAP)
|
|
uniform sampler2D u_LightMap;
|
|
#endif
|
|
|
|
#if defined(USE_NORMALMAP)
|
|
uniform sampler2D u_NormalMap;
|
|
#endif
|
|
|
|
#if defined(USE_DELUXEMAP)
|
|
uniform sampler2D u_DeluxeMap;
|
|
#endif
|
|
|
|
#if defined(USE_SPECULARMAP)
|
|
uniform sampler2D u_SpecularMap;
|
|
#endif
|
|
|
|
#if defined(USE_SHADOWMAP)
|
|
uniform sampler2D u_ShadowMap;
|
|
#endif
|
|
|
|
#if defined(USE_CUBEMAP)
|
|
uniform samplerCube u_CubeMap;
|
|
#endif
|
|
|
|
#if defined(USE_NORMALMAP) || defined(USE_DELUXEMAP) || defined(USE_SPECULARMAP) || defined(USE_CUBEMAP)
|
|
// y = deluxe, w = cube
|
|
uniform vec4 u_EnableTextures;
|
|
#endif
|
|
|
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
|
uniform vec3 u_PrimaryLightColor;
|
|
uniform vec3 u_PrimaryLightAmbient;
|
|
#endif
|
|
|
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
|
uniform vec4 u_NormalScale;
|
|
uniform vec4 u_SpecularScale;
|
|
#endif
|
|
|
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
|
#if defined(USE_CUBEMAP)
|
|
uniform vec4 u_CubeMapInfo;
|
|
#endif
|
|
#endif
|
|
|
|
uniform int u_AlphaTest;
|
|
|
|
varying vec4 var_TexCoords;
|
|
|
|
varying vec4 var_Color;
|
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
|
varying vec4 var_ColorAmbient;
|
|
#endif
|
|
|
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
|
varying vec4 var_Normal;
|
|
varying vec4 var_Tangent;
|
|
varying vec4 var_Bitangent;
|
|
#endif
|
|
|
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
|
varying vec4 var_LightDir;
|
|
#endif
|
|
|
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
|
varying vec4 var_PrimaryLightDir;
|
|
#endif
|
|
|
|
|
|
#define EPSILON 0.00000001
|
|
|
|
#if defined(USE_PARALLAXMAP)
|
|
float SampleDepth(sampler2D normalMap, vec2 t)
|
|
{
|
|
#if defined(SWIZZLE_NORMALMAP)
|
|
return 1.0 - texture2D(normalMap, t).r;
|
|
#else
|
|
return 1.0 - texture2D(normalMap, t).a;
|
|
#endif
|
|
}
|
|
|
|
float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
|
|
{
|
|
const int linearSearchSteps = 16;
|
|
const int binarySearchSteps = 6;
|
|
|
|
// current size of search window
|
|
float size = 1.0 / float(linearSearchSteps);
|
|
|
|
// current depth position
|
|
float depth = 0.0;
|
|
|
|
// best match found (starts with last position 1.0)
|
|
float bestDepth = 1.0;
|
|
|
|
// texture depth at best depth
|
|
float texDepth = 0.0;
|
|
|
|
float prevT = SampleDepth(normalMap, dp);
|
|
float prevTexDepth = prevT;
|
|
|
|
// search front to back for first point inside object
|
|
for(int i = 0; i < linearSearchSteps - 1; ++i)
|
|
{
|
|
depth += size;
|
|
|
|
float t = SampleDepth(normalMap, dp + ds * depth);
|
|
|
|
if(bestDepth > 0.996) // if no depth found yet
|
|
if(depth >= t)
|
|
{
|
|
bestDepth = depth; // store best depth
|
|
texDepth = t;
|
|
prevTexDepth = prevT;
|
|
}
|
|
prevT = t;
|
|
}
|
|
|
|
depth = bestDepth;
|
|
|
|
#if !defined (USE_RELIEFMAP)
|
|
float div = 1.0 / (1.0 + (prevTexDepth - texDepth) * float(linearSearchSteps));
|
|
bestDepth -= (depth - size - prevTexDepth) * div;
|
|
#else
|
|
// recurse around first point (depth) for closest match
|
|
for(int i = 0; i < binarySearchSteps; ++i)
|
|
{
|
|
size *= 0.5;
|
|
|
|
float t = SampleDepth(normalMap, dp + ds * depth);
|
|
|
|
if(depth >= t)
|
|
{
|
|
bestDepth = depth;
|
|
depth -= 2.0 * size;
|
|
}
|
|
|
|
depth += size;
|
|
}
|
|
#endif
|
|
|
|
return bestDepth;
|
|
}
|
|
#endif
|
|
|
|
vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
|
|
{
|
|
#if defined(USE_BURLEY)
|
|
// modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf
|
|
float fd90 = -0.5 + EH * EH * roughness;
|
|
float burley = 1.0 + fd90 * 0.04 / NH;
|
|
burley *= burley;
|
|
return diffuseAlbedo * burley;
|
|
#else
|
|
return diffuseAlbedo;
|
|
#endif
|
|
}
|
|
|
|
vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular)
|
|
{
|
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
|
float v = 1.0 - max(roughness, NE);
|
|
v *= v * v;
|
|
return vec3(v) + specular;
|
|
}
|
|
|
|
vec3 CalcSpecular(vec3 specular, float NH, float EH, float roughness)
|
|
{
|
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
|
float rr = roughness*roughness;
|
|
float rrrr = rr*rr;
|
|
float d = (NH * NH) * (rrrr - 1.0) + 1.0;
|
|
float v = (EH * EH) * (roughness + 0.5);
|
|
return specular * (rrrr / (4.0 * d * d * v));
|
|
}
|
|
|
|
|
|
float CalcLightAttenuation(float point, float normDist)
|
|
{
|
|
// zero light at 1.0, approximating q3 style
|
|
// also don't attenuate directional light
|
|
float attenuation = (0.5 * normDist - 1.5) * point + 1.0;
|
|
|
|
// clamp attenuation
|
|
#if defined(NO_LIGHT_CLAMP)
|
|
attenuation = max(attenuation, 0.0);
|
|
#else
|
|
attenuation = clamp(attenuation, 0.0, 1.0);
|
|
#endif
|
|
|
|
return attenuation;
|
|
}
|
|
|
|
|
|
void main()
|
|
{
|
|
vec3 viewDir, lightColor, ambientColor, reflectance;
|
|
vec3 L, N, E, H;
|
|
float NL, NH, NE, EH, attenuation;
|
|
|
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
|
mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);
|
|
viewDir = vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w);
|
|
E = normalize(viewDir);
|
|
#endif
|
|
|
|
lightColor = var_Color.rgb;
|
|
|
|
#if defined(USE_LIGHTMAP)
|
|
vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
|
|
#if defined(RGBM_LIGHTMAP)
|
|
lightmapColor.rgb *= lightmapColor.a;
|
|
#endif
|
|
#if defined(USE_PBR) && !defined(USE_FAST_LIGHT)
|
|
lightmapColor.rgb *= lightmapColor.rgb;
|
|
#endif
|
|
lightColor *= lightmapColor.rgb;
|
|
#endif
|
|
|
|
vec2 texCoords = var_TexCoords.xy;
|
|
|
|
#if defined(USE_PARALLAXMAP)
|
|
vec3 offsetDir = viewDir * tangentToWorld;
|
|
|
|
offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
|
|
|
|
texCoords += offsetDir.xy * RayIntersectDisplaceMap(texCoords, offsetDir.xy, u_NormalMap);
|
|
#endif
|
|
|
|
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
|
|
|
|
float alpha = diffuse.a * var_Color.a;
|
|
if (u_AlphaTest == 1)
|
|
{
|
|
if (alpha == 0.0)
|
|
discard;
|
|
}
|
|
else if (u_AlphaTest == 2)
|
|
{
|
|
if (alpha >= 0.5)
|
|
discard;
|
|
}
|
|
else if (u_AlphaTest == 3)
|
|
{
|
|
if (alpha < 0.5)
|
|
discard;
|
|
}
|
|
|
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
|
L = var_LightDir.xyz;
|
|
#if defined(USE_DELUXEMAP)
|
|
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
|
|
#endif
|
|
float sqrLightDist = dot(L, L);
|
|
L /= sqrt(sqrLightDist);
|
|
|
|
#if defined(USE_LIGHT_VECTOR)
|
|
attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
|
|
#else
|
|
attenuation = 1.0;
|
|
#endif
|
|
|
|
#if defined(USE_NORMALMAP)
|
|
#if defined(SWIZZLE_NORMALMAP)
|
|
N.xy = texture2D(u_NormalMap, texCoords).ag - vec2(0.5);
|
|
#else
|
|
N.xy = texture2D(u_NormalMap, texCoords).rg - vec2(0.5);
|
|
#endif
|
|
N.xy *= u_NormalScale.xy;
|
|
N.z = sqrt(clamp((0.25 - N.x * N.x) - N.y * N.y, 0.0, 1.0));
|
|
N = tangentToWorld * N;
|
|
#else
|
|
N = var_Normal.xyz;
|
|
#endif
|
|
|
|
N = normalize(N);
|
|
|
|
#if defined(USE_SHADOWMAP)
|
|
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
|
|
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
|
|
|
|
// surfaces not facing the light are always shadowed
|
|
shadowValue *= clamp(dot(N, var_PrimaryLightDir.xyz), 0.0, 1.0);
|
|
|
|
#if defined(SHADOWMAP_MODULATE)
|
|
lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r;
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(USE_LIGHT_VECTOR)
|
|
ambientColor = lightColor;
|
|
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
|
|
|
|
// reserve 25% ambient to avoid black areas on normalmaps
|
|
lightColor *= 0.75;
|
|
|
|
// Scale the incoming light to compensate for the baked-in light angle
|
|
// attenuation.
|
|
lightColor /= max(surfNL, 0.25);
|
|
|
|
// Recover any unused light as ambient, in case attenuation is over 4x or
|
|
// light is below the surface
|
|
ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0));
|
|
#else
|
|
ambientColor = var_ColorAmbient.rgb;
|
|
#endif
|
|
|
|
NL = clamp(dot(N, L), 0.0, 1.0);
|
|
NE = clamp(dot(N, E), 0.0, 1.0);
|
|
H = normalize(L + E);
|
|
EH = clamp(dot(E, H), 0.0, 1.0);
|
|
NH = clamp(dot(N, H), 0.0, 1.0);
|
|
|
|
#if defined(USE_SPECULARMAP)
|
|
vec4 specular = texture2D(u_SpecularMap, texCoords);
|
|
#else
|
|
vec4 specular = vec4(1.0);
|
|
#endif
|
|
specular *= u_SpecularScale;
|
|
|
|
#if defined(USE_PBR)
|
|
diffuse.rgb *= diffuse.rgb;
|
|
#endif
|
|
|
|
#if defined(USE_PBR)
|
|
// diffuse rgb is base color
|
|
// specular red is gloss
|
|
// specular green is metallicness
|
|
float gloss = specular.r;
|
|
float metal = specular.g;
|
|
specular.rgb = metal * diffuse.rgb + vec3(0.04 - 0.04 * metal);
|
|
diffuse.rgb *= 1.0 - metal;
|
|
#else
|
|
// diffuse rgb is diffuse
|
|
// specular rgb is specular reflectance at normal incidence
|
|
// specular alpha is gloss
|
|
float gloss = specular.a;
|
|
|
|
// adjust diffuse by specular reflectance, to maintain energy conservation
|
|
diffuse.rgb *= vec3(1.0) - specular.rgb;
|
|
#endif
|
|
|
|
#if defined(GLOSS_IS_GLOSS)
|
|
float roughness = exp2(-3.0 * gloss);
|
|
#elif defined(GLOSS_IS_SMOOTHNESS)
|
|
float roughness = 1.0 - gloss;
|
|
#elif defined(GLOSS_IS_ROUGHNESS)
|
|
float roughness = gloss;
|
|
#elif defined(GLOSS_IS_SHININESS)
|
|
float roughness = pow(2.0 / (8190.0 * gloss + 2.0), 0.25);
|
|
#endif
|
|
|
|
reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness);
|
|
|
|
#if defined(r_deluxeSpecular)
|
|
#if defined(USE_LIGHT_VECTOR)
|
|
reflectance += CalcSpecular(specular.rgb, NH, EH, roughness) * r_deluxeSpecular;
|
|
#else
|
|
reflectance += CalcSpecular(specular.rgb, NH, EH, pow(roughness, r_deluxeSpecular));
|
|
#endif
|
|
#endif
|
|
|
|
gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
|
|
gl_FragColor.rgb += ambientColor * diffuse.rgb;
|
|
|
|
#if defined(USE_CUBEMAP)
|
|
reflectance = EnvironmentBRDF(roughness, NE, specular.rgb);
|
|
|
|
vec3 R = reflect(E, N);
|
|
|
|
// parallax corrected cubemap (cheaper trick)
|
|
// from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
|
vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
|
|
|
|
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, ROUGHNESS_MIPS * roughness).rgb * u_EnableTextures.w;
|
|
|
|
// normalize cubemap based on last roughness mip (~diffuse)
|
|
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
|
|
//vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, ROUGHNESS_MIPS).rgb, 0.5 / 255.0);
|
|
//cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
|
|
|
|
#if defined(USE_PBR)
|
|
cubeLightColor *= cubeLightColor;
|
|
#endif
|
|
|
|
// multiply cubemap values by lighting
|
|
// not technically correct, but helps make reflections look less unnatural
|
|
//cubeLightColor *= lightColor * (attenuation * NL) + ambientColor;
|
|
|
|
gl_FragColor.rgb += cubeLightColor * reflectance;
|
|
#endif
|
|
|
|
#if defined(USE_PRIMARY_LIGHT) || defined(SHADOWMAP_MODULATE)
|
|
vec3 L2, H2;
|
|
float NL2, EH2, NH2;
|
|
|
|
L2 = var_PrimaryLightDir.xyz;
|
|
|
|
// enable when point lights are supported as primary lights
|
|
//sqrLightDist = dot(L2, L2);
|
|
//L2 /= sqrt(sqrLightDist);
|
|
|
|
NL2 = clamp(dot(N, L2), 0.0, 1.0);
|
|
H2 = normalize(L2 + E);
|
|
EH2 = clamp(dot(E, H2), 0.0, 1.0);
|
|
NH2 = clamp(dot(N, H2), 0.0, 1.0);
|
|
|
|
reflectance = CalcSpecular(specular.rgb, NH2, EH2, roughness);
|
|
|
|
// bit of a hack, with modulated shadowmaps, ignore diffuse
|
|
#if !defined(SHADOWMAP_MODULATE)
|
|
reflectance += CalcDiffuse(diffuse.rgb, NH2, EH2, roughness);
|
|
#endif
|
|
|
|
lightColor = u_PrimaryLightColor;
|
|
|
|
#if defined(USE_SHADOWMAP)
|
|
lightColor *= shadowValue;
|
|
#endif
|
|
|
|
// enable when point lights are supported as primary lights
|
|
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
|
|
|
|
gl_FragColor.rgb += lightColor * reflectance * NL2;
|
|
#endif
|
|
|
|
#if defined(USE_PBR)
|
|
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
|
|
#endif
|
|
|
|
#else
|
|
|
|
gl_FragColor.rgb = diffuse.rgb * lightColor;
|
|
|
|
#endif
|
|
|
|
gl_FragColor.a = alpha;
|
|
}
|