cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
-cvar_t r_shadows_drawafterrtlightning = {CVAR_SAVE, "r_shadows_drawafterrtlightning", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
+cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
-cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
float screentexcoord2f[8];
float bloomtexcoord2f[8];
float offsettexcoord2f[8];
+
+ r_viewport_t viewport;
}
r_bloomstate;
skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
/// vertex coordinates for a quad that covers the screen exactly
-const static float r_screenvertex3f[12] =
+const float r_screenvertex3f[12] =
{
0, 0, 0,
1, 0, 0,
"// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
"// written by Forest 'LordHavoc' Hale\n"
"#ifdef USESHADOWMAPRECT\n"
-"#extension GL_ARB_texture_rectangle : enable\n"
+"# extension GL_ARB_texture_rectangle : enable\n"
"#endif\n"
+"\n"
+"#ifdef USESHADOWMAP2D\n"
+"# ifdef GL_EXT_gpu_shader4\n"
+"# extension GL_EXT_gpu_shader4 : enable\n"
+"# endif\n"
+"# ifdef GL_ARB_texture_gather\n"
+"# extension GL_ARB_texture_gather : enable\n"
+"# define USETEXTUREGATHER\n"
+"# else\n"
+"# ifdef GL_AMD_texture_texture4\n"
+"# extension GL_AMD_texture_texture4 : enable\n"
+"# define USETEXTUREGATHER\n"
+"# define textureGather texture4\n"
+"# endif\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#ifdef USESHADOWMAPCUBE\n"
-"#extension GL_EXT_gpu_shader4 : enable\n"
+"# extension GL_EXT_gpu_shader4 : enable\n"
"#endif\n"
"\n"
"// common definitions between vertex shader and fragment shader:\n"
"//#ifdef __GLSL_CG_DATA_TYPES\n"
"//# define myhalf half\n"
"//# define myhalf2 half2\n"
-"//# define myhalf3 half3\n"
+"//# define myhalf3half3\n"
"//# define myhalf4 half4\n"
"//#else\n"
"# define myhalf float\n"
" gl_FrontColor = gl_Color;\n"
" gl_Position = ftransform();\n"
" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
"#endif\n"
"}\n"
"# ifdef FRAGMENT_SHADER\n"
"\n"
"uniform sampler2D Texture_First;\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
"uniform sampler2D Texture_Second;\n"
"#endif\n"
"#ifdef USEGAMMARAMPS\n"
"#ifdef USESATURATION\n"
"uniform float Saturation;\n"
"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
+"#ifdef USEVIEWTINT\n"
"uniform vec4 TintColor;\n"
"#endif\n"
-"#ifdef USECOLORMOD\n"
-"uniform vec3 Gamma;\n"
-"#endif\n"
"//uncomment these if you want to use them:\n"
"uniform vec4 UserVec1;\n"
"// uniform vec4 UserVec2;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
-"#ifdef USEGLOW\n"
+"#ifdef USEBLOOM\n"
" gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
"#endif\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
+"#ifdef USEVIEWTINT\n"
" gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
"#endif\n"
"\n"
" //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
" myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
-" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
+" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
"#endif\n"
"\n"
"#ifdef USEGAMMARAMPS\n"
"uniform samplerCube Texture_Cube;\n"
"\n"
"#define showshadowmap 0\n"
-"#define useshadowsamplerrect 0\n"
-"#define useshadowsampler2d 0\n"
-"#define useshadowsamplercube 1\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
-"# if useshadowsamplerrect\n"
+"# ifdef USESHADOWSAMPLER\n"
"uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
"# else\n"
"uniform sampler2DRect Texture_ShadowMapRect;\n"
"#endif\n"
"\n"
"#ifdef USESHADOWMAP2D\n"
-"# if useshadowsampler2d\n"
+"# ifdef USESHADOWSAMPLER\n"
"uniform sampler2DShadow Texture_ShadowMap2D;\n"
"# else\n"
"uniform sampler2D Texture_ShadowMap2D;\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"uniform samplerCube Texture_CubeProjection;\n"
+"#endif\n"
+"\n"
"#ifdef USESHADOWMAPCUBE\n"
-"# if useshadowsamplercube\n"
+"# ifdef USESHADOWSAMPLER\n"
"uniform samplerCubeShadow Texture_ShadowMapCube;\n"
"# else\n"
"uniform samplerCube Texture_ShadowMapCube;\n"
"\n"
"uniform myhalf GlowScale;\n"
"uniform myhalf SceneBrightness;\n"
-"#ifdef USECONTRASTBOOST\n"
-"uniform myhalf ContrastBoostCoeff;\n"
-"#endif\n"
"\n"
"uniform float OffsetMapping_Scale;\n"
"uniform float OffsetMapping_Bias;\n"
"#endif // USEOFFSETMAPPING\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
-"//float ShadowMap_TextureSize = 1024.0;\n"
-"//float ShadowMap_BorderSize = 6.0;\n"
-"//float ShadowMap_NearClip = 0.0001;\n"
-"//float ShadowMap_FarClip = 1.0;\n"
-"//float ShadowMap_Bias = ShadowMap_NearClip * 64.0 / ShadowMap_TextureSize;\n"
-"//vec2 ShadowMap_TextureScale = vec2(0.5, 0.25);\n"
-"//vec4 ShadowMap_Parameters = vec3(1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, 1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, -(ShadowMap_FarClip + ShadowMap_NearClip) / (ShadowMap_FarClip - ShadowMap_NearClip), -2.0 * ShadowMap_NearClip * ShadowMap_FarClip / (ShadowMap_FarClip - ShadowMap_NearClip));\n"
-"uniform float ShadowMap_Bias;\n"
-"uniform vec2 ShadowMap_TextureScale;\n"
+"uniform vec4 ShadowMap_TextureScale;\n"
"uniform vec4 ShadowMap_Parameters;\n"
"#endif\n"
"\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" vec3 tc;\n"
-" vec3 offset;\n"
-"# if 1\n"
-" float d;\n"
+"# ifndef USESHADOWMAPVSDCT\n"
+"# ifdef USESHADOWMAPRECT\n"
+"# define cubedir(dx, dy, ox, oy) { tc = vec2(dx, dy); offset = vec2(ox, oy); }\n"
+"# else\n"
+"# define cubedir(dx, dy, ox, oy) { tc = vec2(dx, dy); offset = vec2(ox/2.0, oy/4.0); }\n"
+"# endif\n"
+" vec2 tc;\n"
+" vec2 offset;\n"
+" float ma;\n"
" if (adir.x > adir.y)\n"
" {\n"
" if (adir.x > adir.z)\n"
" {\n"
-" d = 0.5 / adir.x;\n"
-" if (dir.x >= 0.0)\n"
-" {\n"
-" // +X\n"
-" tc = vec3(-dir.z, -dir.y, -dir.x);\n"
-" offset = vec3(0.5, 0.5, 0.5);\n"
-" }\n"
-" else\n"
-" {\n"
-" // -X\n"
-" tc = vec3( dir.z, -dir.y, dir.x);\n"
-" offset = vec3(1.5, 0.5, 0.5);\n"
-" }\n"
+" ma = adir.x;\n"
+" if (dir.x >= 0.0) cubedir(-dir.z, -dir.y, 0.5, 0.5) // +X\n"
+" else cubedir( dir.z, -dir.y, 1.5, 0.5) // -X\n"
" }\n"
" else\n"
" {\n"
-" d = 0.5 / adir.z;\n"
-" if (dir.z >= 0.0)\n"
-" {\n"
-" // +Z\n"
-" tc = vec3( dir.x, -dir.y, -dir.z);\n"
-" offset = vec3(0.5, 2.5, 0.5);\n"
-" }\n"
-" else\n"
-" {\n"
-" // -Z\n"
-" tc = vec3(-dir.x, -dir.y, dir.z);\n"
-" offset = vec3(1.5, 2.5, 0.5);\n"
-" }\n"
+" ma = adir.z;\n"
+" if (dir.z >= 0.0) cubedir( dir.x, -dir.y, 0.5, 2.5) // +Z\n"
+" else cubedir(-dir.x, -dir.y, 1.5, 2.5) // -Z\n"
" }\n"
" }\n"
" else\n"
" {\n"
" if (adir.y > adir.z)\n"
" {\n"
-" d = 0.5 / adir.y;\n"
-" if (dir.y >= 0.0)\n"
-" {\n"
-" // +Y\n"
-" tc = vec3( dir.x, dir.z, -dir.y);\n"
-" offset = vec3(0.5, 1.5, 0.5);\n"
-" }\n"
-" else\n"
-" {\n"
-" // -Y\n"
-" tc = vec3( dir.x, -dir.z, dir.y);\n"
-" offset = vec3(1.5, 1.5, 0.5);\n"
-" }\n"
+" ma = adir.y;\n"
+" if (dir.y >= 0.0) cubedir( dir.x, dir.z, 0.5, 1.5) // +Y\n"
+" else cubedir( dir.x, -dir.z, 1.5, 1.5) // -Y\n"
" }\n"
" else\n"
" {\n"
-" d = 0.5 / adir.z;\n"
-" if (dir.z >= 0.0)\n"
-" {\n"
-" // +Z\n"
-" tc = vec3(dir.x, -dir.y, -dir.z);\n"
-" offset = vec3(0.5, 2.5, 0.5);\n"
-" }\n"
-" else\n"
-" {\n"
-" // -Z\n"
-" tc = vec3(-dir.x, -dir.y, dir.z);\n"
-" offset = vec3(1.5, 2.5, 0.5);\n"
-" }\n"
+" ma = adir.z;\n"
+" if (dir.z >= 0.0) cubedir( dir.x, -dir.y, 0.5, 2.5) // +Z\n"
+" else cubedir(-dir.x, -dir.y, 1.5, 2.5) // -Z\n"
" }\n"
" }\n"
-" tc = tc * ShadowMap_Parameters.xyz * d + offset;\n"
-" tc.xy *= ShadowMap_TextureScale;\n"
-" tc.z += ShadowMap_Parameters.w * d - ShadowMap_Bias * d;\n"
-"# else\n"
-" // experimental method by eihrul, needs overhaul\n"
-" vec3 ma = vec3(0.0, 0.0, 1.0);\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z)\n"
-" ma = vec3(1.0, 0.0, 0.0);\n"
-" }\n"
-" else if (adir.y > adir.z)\n"
-" ma = vec3(0.0, 1.0, 0.0);\n"
"\n"
-" tc.xy = dir.xy - ma.xy*(dir.xy - dir.z);\n"
-" tc.xy = (tc.xy/dot(ma, dir))*0.5 + 0.5;\n"
-" tc.z = dot(ma, adir);\n"
-" tc.xy = (tc.xy * tcscale + offset) * vec2(0.5, 0.25);\n"
+"# ifdef USESHADOWMAPRECT\n"
+" return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
+"# else\n"
+" return vec3(tc * ShadowMap_Parameters.xy, ShadowMap_Parameters.w) / ma + vec3(offset, ShadowMap_Parameters.z);\n"
+"# endif\n"
+"# else\n"
+"# ifdef USESHADOWMAPRECT \n"
+" return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_TextureScale.xy, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+"# else\n"
+" return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+"# endif\n"
"# endif\n"
-" return tc;\n"
"}\n"
-"\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"#ifdef USESHADOWMAPCUBE\n"
"vec4 GetShadowMapTCCube(vec3 dir)\n"
"{\n"
-" vec3 adir = abs(dir);\n"
-" float sidedist = max(adir.x, max(adir.y, adir.z));\n"
-" return vec4(dir, 0.5 - 0.5 * (ShadowMap_Parameters.z - (-ShadowMap_Bias + ShadowMap_Parameters.w) / sidedist));\n"
+" vec3 adir = abs(dir);\n"
+" return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"{\n"
" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
" float f;\n"
-"# if useshadowsamplerrect\n"
-" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).a;\n"
+"# ifdef USESHADOWSAMPLER\n"
+"\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
+" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# else\n"
+" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
+"# endif\n"
+"\n"
"# else\n"
-" f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+"\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
+"# if 1\n"
+" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0))),\n"
+" row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0))),\n"
+" row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0))),\n"
+" row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0))),\n"
+" cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"# else\n"
+" vec2 offset = fract(shadowmaptc.xy);\n"
+" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0))),\n"
+" row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)))\n"
+" row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0))),\n"
+" cols = row2 + mix(row1, row3, offset.y);\n"
+" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+"# endif\n"
+"# else\n"
+" f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+"# endif\n"
+"\n"
"# endif\n"
" return f;\n"
"}\n"
"# ifdef USESHADOWMAP2D\n"
"float ShadowMapCompare(vec3 dir)\n"
"{\n"
-" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
-" float f;\n"
-"# if useshadowsampler2d\n"
-" f = shadow2D(Texture_ShadowMap2D, shadowmaptc).a;\n"
+" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
+" float f;\n"
+"\n"
+"# ifdef USESHADOWSAMPLER\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# ifdef GL_EXT_gpu_shader4\n"
+"# define texval(x, y) shadow2DOffset(Texture_ShadowMap2D, shadowmaptc, ivec2(x, y)).r\n"
+"# else\n"
+"# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy + vec2(x, y)*ShadowMap_TextureScale.xy, shadowmaptc.z)).r \n"
+"# endif\n"
+" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# else\n"
+" f = shadow2D(Texture_ShadowMap2D, shadowmaptc).r;\n"
+"# endif\n"
"# else\n"
-" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# ifdef USETEXTUREGATHER\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw - 0.5, offset = fract(center);\n"
+" vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
+" group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
+" group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, 1.0))*ShadowMap_TextureScale.xy)),\n"
+" group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, 1.0))*ShadowMap_TextureScale.xy)),\n"
+" cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
+" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"# else\n"
+"# ifdef GL_EXT_gpu_shader4\n"
+" vec2 center = shadowmaptc.xy - 0.5*ShadowMap_TextureScale.xy, offset = fract(center*ShadowMap_TextureScale.zw);\n"
+"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
+"# else\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw - 0.5, offset = fract(center);\n"
+"# define texval(x, y) texture2D(Texture_ShadowMap2D, (center + vec2(x, y))*ShadowMap_TextureScale.xy).r \n"
+"# endif\n"
+" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0))),\n"
+" row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0))),\n"
+" row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0))),\n"
+" row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0))),\n"
+" cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"# endif\n"
+"# else\n"
+" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
+"# endif\n"
"# endif\n"
-" return f;\n"
+" return f;\n"
"}\n"
"# endif\n"
"\n"
"# ifdef USESHADOWMAPCUBE\n"
"float ShadowMapCompare(vec3 dir)\n"
"{\n"
-" // apply depth texture cubemap as light filter\n"
-" vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
-" float f;\n"
-"# if useshadowsamplercube\n"
-" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).a;\n"
+" // apply depth texture cubemap as light filter\n"
+" vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
+" float f;\n"
+"# ifdef USESHADOWSAMPLER\n"
+" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
"# else\n"
-" f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
+" f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
"# endif\n"
-" return f;\n"
+" return f;\n"
"}\n"
"# endif\n"
"#endif\n"
"\n"
-"\n"
"#ifdef MODE_WATER\n"
"\n"
"// water pass\n"
"\n"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-" vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+" vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
+" f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
" gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
"}\n"
"\n"
" vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-" vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+" vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
" gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
"}\n"
"\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
"#if !showshadowmap\n"
-" color.rgb *= ShadowMapCompare(CubeVector);\n"
+" color.rgb *= ShadowMapCompare(CubeVector);\n"
"#endif\n"
"#endif\n"
"\n"
"#endif\n"
"#endif\n"
"\n"
-"#ifdef USECONTRASTBOOST\n"
-" color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
-"#endif\n"
-"\n"
" color.rgb *= SceneBrightness;\n"
"\n"
" // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
"#ifdef USEREFLECTION\n"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-" vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-" color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
+" vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
"#endif\n"
"\n"
" gl_FragColor = vec4(color);\n"
"\n"
"#if showshadowmap\n"
"# ifdef USESHADOWMAPRECT\n"
-"# if useshadowsamplerrect\n"
+"# ifdef USESHADOWSAMPLER\n"
" gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
"# else\n"
" gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
"# endif\n"
"# endif\n"
-"\n"
"# ifdef USESHADOWMAP2D\n"
-"# if useshadowsampler2d\n"
-" gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
+"# ifdef USESHADOWSAMPLER\n"
+" gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
"# else\n"
-" gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
+" gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
"# endif\n"
"# endif\n"
"\n"
"# ifdef USESHADOWMAPCUBE\n"
-"# if useshadowsamplercube\n"
-" gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
+"# ifdef USESHADOWSAMPLER\n"
+" gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
"# else\n"
-" gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
+" gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
"# endif\n"
"# endif\n"
"#endif\n"
{
SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
+ SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
- SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
- SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
- SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
- SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
- SHADERPERMUTATION_SHADOWMAPRECT = 1<<15, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<16, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
+ SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
+ SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
+ SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<15, //< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<16, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_LIMIT = 1<<17, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 17 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
{
{"#define USEDIFFUSE\n", " diffuse"},
- {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
- {"#define USECOLORMAPPING\n", " colormapping"},
- {"#define USECONTRASTBOOST\n", " contrastboost"},
- {"#define USEFOG\n", " fog"},
+ {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
+ {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
+ {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
- {"#define USEGLOW\n", " glow"},
- {"#define USESPECULAR\n", " specular"},
+ {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
+ {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
{"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
{"#define USEREFLECTION\n", " reflection"},
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
- {"#define USEGAMMARAMPS\n", " gammaramps"},
- {"#define USEPOSTPROCESSING\n", " postprocessing"},
- {"#define USESATURATION\n", " saturation"},
{"#define USESHADOWMAPRECT\n", " shadowmaprect"},
{"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
{"#define USESHADOWMAP2D\n", " shadowmap2d"},
+ {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
+ {"#define USESHADOWSAMPLER\n", " shadowsampler"},
+ {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
};
+struct r_glsl_permutation_s;
typedef struct r_glsl_permutation_s
{
+ /// hash lookup data
+ struct r_glsl_permutation_s *hashnext;
+ unsigned int mode;
+ unsigned int permutation;
+
/// indicates if we have tried compiling this permutation already
qboolean compiled;
/// 0 if compilation failed
int loc_Texture_ShadowMapRect;
int loc_Texture_ShadowMapCube;
int loc_Texture_ShadowMap2D;
+ int loc_Texture_CubeProjection;
int loc_FogColor;
int loc_LightPosition;
int loc_EyePosition;
int loc_ClientTime;
int loc_PixelSize;
int loc_Saturation;
- int loc_ShadowMap_Bias;
int loc_ShadowMap_TextureScale;
int loc_ShadowMap_Parameters;
}
r_glsl_permutation_t;
+#define SHADERPERMUTATION_HASHSIZE 4096
+
/// information about each possible shader permutation
-r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
+r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
/// currently selected permutation
r_glsl_permutation_t *r_glsl_permutation;
+/// storage for permutations linked in the hash table
+memexpandablearray_t r_glsl_permutationarray;
+
+static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+{
+ //unsigned int hashdepth = 0;
+ unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
+ r_glsl_permutation_t *p;
+ for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
+ {
+ if (p->mode == mode && p->permutation == permutation)
+ {
+ //if (hashdepth > 10)
+ // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
+ return p;
+ }
+ //hashdepth++;
+ }
+ p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
+ p->mode = mode;
+ p->permutation = permutation;
+ p->hashnext = r_glsl_permutationhash[mode][hashindex];
+ r_glsl_permutationhash[mode][hashindex] = p;
+ //if (hashdepth > 10)
+ // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
+ return p;
+}
static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
{
return shaderstring;
}
-static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
+static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
{
int i;
shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
- r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
int vertstrings_count = 0;
int geomstrings_count = 0;
int fragstrings_count = 0;
p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
+ p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
- p->loc_ShadowMap_Bias = qglGetUniformLocationARB(p->program, "ShadowMap_Bias");
p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
+ if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
CHECKGLERROR
if (developer.integer)
Con_Printf("GLSL shader %s compiled.\n", permutationname);
void R_GLSL_Restart_f(void)
{
- unsigned int mode;
- unsigned int permutation;
- for (mode = 0;mode < SHADERMODE_COUNT;mode++)
- for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
- if (r_glsl_permutations[mode][permutation].program)
- GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
- memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
+ unsigned int i, limit;
+ r_glsl_permutation_t *p;
+ limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
+ for (i = 0;i < limit;i++)
+ {
+ if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
+ {
+ GL_Backend_FreeProgram(p->program);
+ Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
+ }
+ }
+ memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
}
void R_GLSL_DumpShader_f(void)
return;
}
- FS_Print(file, "// The engine may define the following macros:\n");
- FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
+ FS_Print(file, "/* The engine may define the following macros:\n");
+ FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
for (i = 0;i < SHADERMODE_COUNT;i++)
- FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
+ FS_Print(file, shadermodeinfo[i].pretext);
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
- FS_Print(file, "\n");
+ FS_Print(file, shaderpermutationinfo[i].pretext);
+ FS_Print(file, "*/\n");
FS_Print(file, builtinshaderstring);
FS_Close(file);
void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
{
- r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
+ r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
if (r_glsl_permutation != perm)
{
r_glsl_permutation = perm;
if (!r_glsl_permutation->program)
{
if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(mode, permutation);
+ R_GLSL_CompilePermutation(perm, mode, permutation);
if (!r_glsl_permutation->program)
{
// remove features until we find a valid permutation
if (!(permutation & j))
continue;
permutation -= j;
- r_glsl_permutation = &r_glsl_permutations[mode][permutation];
+ r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(mode, permutation);
+ R_GLSL_CompilePermutation(perm, mode, permutation);
if (r_glsl_permutation->program)
break;
}
extern qboolean r_shadow_usingshadowmaprect;
extern qboolean r_shadow_usingshadowmapcube;
extern qboolean r_shadow_usingshadowmap2d;
-extern float r_shadow_shadowmap_bias;
-extern float r_shadow_shadowmap_texturescale[2];
+extern float r_shadow_shadowmap_texturescale[4];
extern float r_shadow_shadowmap_parameters[4];
+extern int r_shadow_shadowmapvsdct;
+extern int r_shadow_shadowmapfilter;
void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
{
// select a permutation of the lighting shader appropriate to this
permutation |= SHADERPERMUTATION_FOG;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
- permutation |= SHADERPERMUTATION_CONTRASTBOOST;
- if (r_shadow_usingshadowmaprect)
- permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
- if (r_shadow_usingshadowmapcube)
- permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
- if (r_shadow_usingshadowmap2d)
- permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+ if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
+ {
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+ if (r_shadow_usingshadowmapcube)
+ permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
+ else if(r_shadow_shadowmapvsdct)
+ permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
+
+ if (r_shadow_shadowmapfilter == 3)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ else if (r_shadow_shadowmapfilter == 2)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
+ else if (r_shadow_shadowmapfilter == 1)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ }
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
- if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
- permutation |= SHADERPERMUTATION_CONTRASTBOOST;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
permutation |= SHADERPERMUTATION_FOG;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
- permutation |= SHADERPERMUTATION_CONTRASTBOOST;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
permutation |= SHADERPERMUTATION_FOG;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
- permutation |= SHADERPERMUTATION_CONTRASTBOOST;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
permutation |= SHADERPERMUTATION_FOG;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
- permutation |= SHADERPERMUTATION_CONTRASTBOOST;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
}
// additive passes are only darkened by fog, not tinted
if (r_glsl_permutation->loc_FogColor >= 0)
qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
- if (r_glsl_permutation->loc_ShadowMap_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_ShadowMap_Bias, r_shadow_shadowmap_bias);
- if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+ if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
}
else
if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
}
- if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
- {
- // The formula used is actually:
- // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
- // color.rgb *= SceneBrightness;
- // simplified:
- // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
- // and do [[calculations]] here in the engine
- qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
- if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
- }
- else
- if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
+ if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
if (r_glsl_permutation->loc_Color_Pants >= 0)
{
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
- memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
+ memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
+ Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
memset(&r_svbsp, 0, sizeof (r_svbsp));
r_refdef.fogmasktable_density = 0;
Cvar_RegisterVariable(&r_fullbright);
Cvar_RegisterVariable(&r_shadows);
Cvar_RegisterVariable(&r_shadows_darken);
- Cvar_RegisterVariable(&r_shadows_drawafterrtlightning);
+ Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
Cvar_RegisterVariable(&r_shadows_castfrombmodels);
Cvar_RegisterVariable(&r_shadows_throwdistance);
Cvar_RegisterVariable(&r_shadows_throwdirection);
Cvar_RegisterVariable(&r_drawfog);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&r_glsl);
- Cvar_RegisterVariable(&r_glsl_contrastboost);
Cvar_RegisterVariable(&r_glsl_deluxemapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
}
if (!r_refdef.view.useperspective)
- R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+ R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
else if (gl_stencil && r_useinfinitefarclip.integer)
- R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
+ R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
else
- R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
+ R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
R_SetViewport(&r_refdef.view.viewport);
}
DrawQ_Finish();
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
- R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
+ R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
R_SetViewport(&viewport);
- GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
+ GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
{
DrawQ_Finish();
- // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
- qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
R_SetupView(true);
- GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
+ GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
// set waterwidth and waterheight to the water resolution that will be
// used (often less than the screen resolution for faster rendering)
- waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
- waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+ waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
+ waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
// calculate desired texture sizes
// can't use water if the card does not support the texture size
r_waterstate.textureheight = textureheight;
}
+ // when doing a reduced render (HDR) we want to use a smaller area
+ waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
+ waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
+
if (r_waterstate.waterwidth)
{
r_waterstate.enabled = true;
R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
}
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
}
}
r_waterstate.renderingscene = false;
// set bloomwidth and bloomheight to the bloom resolution that will be
// used (often less than the screen resolution for faster rendering)
- r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
- r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
- r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
- r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
- r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
+ r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
+ r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
+ r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
// calculate desired texture sizes
if (gl_support_arb_texture_non_power_of_two)
r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
}
+ // when doing a reduced render (HDR) we want to use a smaller area
+ r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
+ r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
+ r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
+ r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
+
// set up a texcoord array for the full resolution screen image
// (we have to keep this around to copy back during final render)
r_bloomstate.screentexcoord2f[0] = 0;
r_bloomstate.enabled = true;
r_bloomstate.hdr = r_hdr.integer != 0;
}
+
+ R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
}
void R_Bloom_CopyBloomTexture(float colorscale)
// scale down screen texture to the bloom texture size
CHECKGLERROR
- qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ R_SetViewport(&r_bloomstate.viewport);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
// TODO: optimize with multitexture or GLSL
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
void R_Bloom_CopyHDRTexture(void)
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
void R_Bloom_MakeTexture(void)
// we have a bloom image in the framebuffer
CHECKGLERROR
- qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
+ R_SetViewport(&r_bloomstate.viewport);
for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
{
// copy the vertically blurred bloom view to a texture
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
// copy the vertically blurred bloom view to a texture
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
// apply subtract last
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
}
if (r_timereport_active)
R_TimeReport("visibility");
+ // only do secondary renders with HDR if r_hdr is 2 or higher
r_waterstate.numwaterplanes = 0;
- if (r_waterstate.enabled)
+ if (r_waterstate.enabled && r_hdr.integer >= 2)
R_RenderWaterPlanes();
r_refdef.view.showdebug = true;
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
}
// copy view into the screen texture
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
- r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
{
unsigned int permutation =
- (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
- | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
+ (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
+ | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
| ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
| (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
| ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
if (r_glsl_permutation->loc_Saturation >= 0)
qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
return;
}
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
else if (r_bloomstate.texture_bloom)
{
{
R_SetupGenericShader(true);
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
// now blend on the bloom texture
GL_BlendFunc(GL_ONE, GL_ONE);
R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
}
R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
- r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
+ r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
{
vec3_t fogvec;
VectorCopy(r_refdef.fogcolor, fogvec);
- if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
- {
- // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
- fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
- fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
- fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
- }
// color.rgb *= ContrastBoost * SceneBrightness;
VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
+ if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
+ if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();