X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=cef68dc50b3089d41912d2068b995b84ddbcaa2e;hb=980ac035e70ad26a44913dabebe4be5726f966ac;hp=f98be95a5edf45f38be67ee29e1e2c4cdfdb22c2;hpb=c09e10b6153bf23fd0cf62a89c64e6f655fddc6d;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index f98be95a..cef68dc5 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -79,7 +79,7 @@ cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlightin 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_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; +cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "4", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"}; cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"}; cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"}; @@ -191,8 +191,15 @@ unsigned int r_queries[R_MAX_OCCLUSION_QUERIES]; unsigned int r_numqueries; unsigned int r_maxqueries; -char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH]; -skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD]; +typedef struct r_qwskincache_s +{ + char name[MAX_QPATH]; + skinframe_t *skinframe; +} +r_qwskincache_t; + +static r_qwskincache_t *r_qwskincache; +static int r_qwskincache_size; /// vertex coordinates for a quad that covers the screen exactly const float r_screenvertex3f[12] = @@ -447,11 +454,32 @@ static void R_BuildFogTexture(void) static const char *builtinshaderstring = "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n" "// written by Forest 'LordHavoc' Hale\n" +"\n" +"// enable various extensions depending on permutation:\n" +"\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" +"# else\n" +"# ifdef GL_AMD_texture_texture4\n" +"# extension GL_AMD_texture_texture4 : enable\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" +"#ifdef USESHADOWSAMPLER\n" +"# extension GL_ARB_shadow : enable\n" "#endif\n" "\n" "// common definitions between vertex shader and fragment shader:\n" @@ -459,7 +487,7 @@ static const char *builtinshaderstring = "//#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" @@ -554,7 +582,7 @@ static const char *builtinshaderstring = " //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" @@ -761,12 +789,9 @@ static const char *builtinshaderstring = "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" @@ -774,15 +799,19 @@ static const char *builtinshaderstring = "#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" @@ -827,7 +856,7 @@ static const char *builtinshaderstring = "//# endif\n" "//#endif\n" "\n" -"uniform myhalf GlowScale;\n" +"uniform myhalf3 GlowColor;\n" "uniform myhalf SceneBrightness;\n" "\n" "uniform float OffsetMapping_Scale;\n" @@ -885,14 +914,6 @@ static const char *builtinshaderstring = "#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_Parameters;\n" "#endif\n" @@ -901,110 +922,67 @@ static const char *builtinshaderstring = "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" +" vec2 tc;\n" +" vec2 offset;\n" +" float ma;\n" " if (adir.x > adir.y)\n" " {\n" -" if (adir.x > adir.z)\n" +" if (adir.x > adir.z) // X\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" +" tc = dir.zy;\n" +" offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n" " }\n" -" else\n" +" else // Z\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" +" tc = dir.xy;\n" +" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n" " }\n" " }\n" " else\n" " {\n" -" if (adir.y > adir.z)\n" +" if (adir.y > adir.z) // Y\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" +" tc = dir.xz;\n" +" offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n" " }\n" -" else\n" +" else // Z\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" +" tc = dir.xy;\n" +" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\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" +" vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n" +" stc.xy += offset * ShadowMap_Parameters.y;\n" +" stc.z += ShadowMap_Parameters.z;\n" +"# if showshadowmap\n" +" stc.xy *= ShadowMap_TextureScale;\n" +"# endif\n" +" return stc;\n" +"# else\n" +" vec4 proj = textureCube(Texture_CubeProjection, dir);\n" +" float ma = max(max(adir.x, adir.y), adir.z);\n" +" vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n" +" stc.xy += proj.zw * ShadowMap_Parameters.y;\n" +" stc.z += ShadowMap_Parameters.z;\n" +"# if showshadowmap\n" +" stc.xy *= ShadowMap_TextureScale;\n" +"# endif\n" +" return stc;\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" @@ -1014,10 +992,40 @@ static const char *builtinshaderstring = "{\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" +"# if USESHADOWMAPPCF > 1\n" +"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\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" +" vec4 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" +" vec4 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" +" vec4 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" +" vec4 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" +"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\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" +" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n" +" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n" +" vec3 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" @@ -1026,34 +1034,82 @@ static const char *builtinshaderstring = "# 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" +"# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n" +" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\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, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n" +"# endif\n" "# else\n" -" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n" +"# ifdef USESHADOWMAPPCF\n" +"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n" +"# ifdef GL_ARB_texture_gather\n" +"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n" +"# else\n" +"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n" +"# endif\n" +" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n" +" center *= ShadowMap_TextureScale;\n" +" vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n" +" vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n" +" vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n" +" vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n" +" vec4 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" +"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n" +"# else\n" +"# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n" +"# endif\n" +"# if USESHADOWMAPPCF > 1\n" +" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n" +" center *= ShadowMap_TextureScale;\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" +" vec4 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" +" vec4 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" +" vec4 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" +" vec4 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 center = shadowmaptc.xy*ShadowMap_TextureScale, 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" +" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n" +" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n" +" vec3 cols = row2 + mix(row1, row3, offset.y);\n" +" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n" +"# endif\n" +"# endif\n" +"# else\n" +" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).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" @@ -1191,7 +1247,7 @@ static const char *builtinshaderstring = "\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" @@ -1324,7 +1380,7 @@ static const char *builtinshaderstring = "#ifdef USEVERTEXTEXTUREBLEND\n" " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n" "#else\n" -" color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n" +" color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n" "#endif\n" "#endif\n" "\n" @@ -1358,26 +1414,25 @@ static const char *builtinshaderstring = "\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" @@ -1431,8 +1486,12 @@ typedef enum shaderpermutation_e 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_LIMIT = 1<<14, ///< size of permutations array - SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array + SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, //< (lightsource) use higher quality percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, //< (lightsource) use hardware shadowmap test + SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing + SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array + SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array } shaderpermutation_t; @@ -1453,6 +1512,10 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USESHADOWMAPRECT\n", " shadowmaprect"}, {"#define USESHADOWMAPCUBE\n", " shadowmapcube"}, {"#define USESHADOWMAP2D\n", " shadowmap2d"}, + {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, + {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, + {"#define USESHADOWSAMPLER\n", " shadowsampler"}, + {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, }; /// this enum is multiplied by SHADERPERMUTATION_MODEBASE @@ -1493,8 +1556,14 @@ shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] = {"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 @@ -1523,6 +1592,7 @@ typedef struct r_glsl_permutation_s 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; @@ -1533,7 +1603,7 @@ typedef struct r_glsl_permutation_s int loc_DiffuseScale; int loc_SpecularScale; int loc_SpecularPower; - int loc_GlowScale; + int loc_GlowColor; int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost int loc_OffsetMapping_Scale; int loc_TintColor; @@ -1557,16 +1627,44 @@ typedef struct r_glsl_permutation_s 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) { @@ -1588,11 +1686,10 @@ 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; @@ -1690,6 +1787,7 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio 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"); @@ -1700,7 +1798,7 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale"); p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower"); p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale"); - p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale"); + p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor"); p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness"); p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale"); p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor"); @@ -1724,7 +1822,6 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio 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 @@ -1751,6 +1848,7 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio 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); @@ -1769,13 +1867,18 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio 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) @@ -1804,14 +1907,14 @@ void R_GLSL_DumpShader_f(void) 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 @@ -1823,9 +1926,9 @@ void R_SetupShader_SetPermutation(unsigned int mode, unsigned int 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; } @@ -1911,9 +2014,11 @@ extern rtexture_t *r_shadow_attenuation3dtexture; 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_parameters[4]; +extern qboolean r_shadow_shadowmapvsdct; +extern qboolean r_shadow_shadowmapsampler; +extern int r_shadow_shadowmappcf; 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 @@ -1953,12 +2058,24 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f permutation |= SHADERPERMUTATION_FOG; if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; - 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_shadowmapsampler) + permutation |= SHADERPERMUTATION_SHADOWSAMPLER; + if (r_shadow_shadowmappcf > 1) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; + } } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { @@ -2082,7 +2199,6 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f // 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_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]); } @@ -2102,7 +2218,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale); } if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]); - if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value); + if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value); // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) { @@ -2321,7 +2437,8 @@ skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int texturefl int basepixels_height; skinframe_t *skinframe; - *has_alpha = false; + if (has_alpha) + *has_alpha = false; if (cls.state == ca_dedicated) return NULL; @@ -2365,7 +2482,8 @@ skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int texturefl if (j < basepixels_width * basepixels_height * 4) { // has transparent pixels - *has_alpha = true; + if (has_alpha) + *has_alpha = true; pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); for (j = 0;j < image_width * image_height * 4;j += 4) { @@ -2423,8 +2541,7 @@ skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int texturefl skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain) { - qboolean has_alpha; - return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha); + return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL); } static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force) @@ -2606,8 +2723,8 @@ void gl_main_start(void) r_maxqueries = 0; memset(r_queries, 0, sizeof(r_queries)); - memset(r_qwskincache, 0, sizeof(r_qwskincache)); - memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe)); + r_qwskincache = NULL; + r_qwskincache_size = 0; // set up r_skinframe loading system for textures memset(&r_skinframe, 0, sizeof(r_skinframe)); @@ -2627,7 +2744,8 @@ void gl_main_start(void) //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; @@ -2643,8 +2761,8 @@ void gl_main_shutdown(void) r_maxqueries = 0; memset(r_queries, 0, sizeof(r_queries)); - memset(r_qwskincache, 0, sizeof(r_qwskincache)); - memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe)); + r_qwskincache = NULL; + r_qwskincache_size = 0; // clear out the r_skinframe state Mem_ExpandableArray_FreeArray(&r_skinframe.array); @@ -2675,6 +2793,10 @@ void gl_main_newmap(void) // FIXME: move this code to client int l; char *entities, entname[MAX_QPATH]; + if (r_qwskincache) + Mem_Free(r_qwskincache); + r_qwskincache = NULL; + r_qwskincache_size = 0; if (cl.worldmodel) { strlcpy(entname, cl.worldmodel->name, sizeof(entname)); @@ -3159,6 +3281,45 @@ static void R_View_UpdateEntityLighting (void) } } +#define MAX_LINEOFSIGHTTRACES 64 + +static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs) +{ + int i; + vec3_t boxmins, boxmaxs; + vec3_t start; + vec3_t end; + dp_model_t *model = r_refdef.scene.worldmodel; + + if (!model || !model->brush.TraceLineOfSight) + return true; + + // expand the box a little + boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0]; + boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0]; + boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1]; + boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1]; + boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2]; + boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2]; + + // try center + VectorCopy(eye, start); + VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end); + if (model->brush.TraceLineOfSight(model, start, end)) + return true; + + // try various random positions + for (i = 0;i < numsamples;i++) + { + VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2])); + if (model->brush.TraceLineOfSight(model, start, end)) + return true; + } + + return false; +} + + static void R_View_UpdateEntityVisible (void) { int i, renderimask; @@ -3185,9 +3346,9 @@ static void R_View_UpdateEntityVisible (void) for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*'))) + if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & (RENDER_VIEWMODEL + RENDER_NOCULL)) && !(ent->model && (ent->model->name[0] == '*'))) { - if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs)) + if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs)) ent->last_trace_visibility = realtime; if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value) r_refdef.viewcache.entityvisible[i] = 0; @@ -3582,7 +3743,7 @@ static void R_Water_StartFrame(void) } // allocate textures as needed - if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight) + if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight) { r_waterstate.maxwaterplanes = MAX_WATERPLANES; for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++) @@ -3595,25 +3756,23 @@ static void R_Water_StartFrame(void) p->texture_reflection = NULL; } memset(&r_waterstate, 0, sizeof(r_waterstate)); - r_waterstate.waterwidth = waterwidth; - r_waterstate.waterheight = waterheight; r_waterstate.texturewidth = texturewidth; 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) + if (r_waterstate.texturewidth) { r_waterstate.enabled = true; + // when doing a reduced render (HDR) we want to use a smaller area + r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width); + r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height); + // set up variables that will be used in shader setup - r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth; - r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight; - r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth; - r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight; + r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth; + r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight; + r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth; + r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight; } r_waterstate.maxwaterplanes = MAX_WATERPLANES; @@ -3965,6 +4124,9 @@ void R_Bloom_MakeTexture(void) brighten = r_bloom_brighten.value; if (r_hdr.integer) brighten *= r_hdr_range.value; + brighten = sqrt(brighten); + if(range >= 1) + brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle" R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom)); R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0); @@ -3972,6 +4134,7 @@ void R_Bloom_MakeTexture(void) { // blend on at multiple vertical offsets to achieve a vertical blur // TODO: do offset blends using GLSL + // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges GL_BlendFunc(GL_ONE, GL_ZERO); for (x = -range;x <= range;x++) { @@ -3992,8 +4155,10 @@ void R_Bloom_MakeTexture(void) // black at the edges // (probably not realistic but looks good enough) //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1); - //r = (dir ? 1.0f : brighten)/(range*2+1); - r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range)); + //r = brighten/(range*2+1); + r = brighten / (range * 2 + 1); + if(range >= 1) + r *= (1 - x*x/(float)(range*range)); GL_Color(r, r, r, 1); R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; @@ -4492,7 +4657,7 @@ void R_RenderView(void) return; } - if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/) + if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/) return; //Host_Error ("R_RenderView: NULL worldmodel"); r_refdef.view.colorscale = r_hdr_scenebrightness.value; @@ -5260,6 +5425,33 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t Matrix4x4_Concat(texmatrix, &matrix, &temp); } +void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname) +{ + int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS; + char name[MAX_QPATH]; + skinframe_t *skinframe; + unsigned char pixels[296*194]; + strlcpy(cache->name, skinname, sizeof(cache->name)); + dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name); + if (developer_loading.integer) + Con_Printf("loading %s\n", name); + skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false); + if (!skinframe || !skinframe->base) + { + unsigned char *f; + fs_offset_t filesize; + skinframe = NULL; + f = FS_LoadFile(name, tempmempool, true, &filesize); + if (f) + { + if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194)) + skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height); + Mem_Free(f); + } + } + cache->skinframe = skinframe; +} + texture_t *R_GetCurrentTexture(texture_t *t) { int i; @@ -5302,14 +5494,16 @@ texture_t *R_GetCurrentTexture(texture_t *t) // update currentskinframe to be a qw skin or animation frame if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) { - if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin)) + if (!r_qwskincache || r_qwskincache_size != cl.maxclients) { - strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i])); - if (developer_loading.integer) - Con_Printf("loading skins/%s\n", r_qwskincache[i]); - r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0); - } - t->currentskinframe = r_qwskincache_skinframe[i]; + r_qwskincache_size = cl.maxclients; + if (r_qwskincache) + Mem_Free(r_qwskincache); + r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size); + } + if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin)) + R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin); + t->currentskinframe = r_qwskincache[i].skinframe; if (t->currentskinframe == NULL) t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes]; } @@ -5397,8 +5591,11 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->glosstexture = r_texture_white; t->backgroundglosstexture = r_texture_white; t->specularscale = r_shadow_gloss2intensity.value; + t->specularpower = r_shadow_gloss2exponent.value; } } + t->specularscale *= t->specularscalemod; + t->specularpower *= t->specularpowermod; // lightmaps mode looks bad with dlights using actual texturing, so turn // off the colormap and glossmap, but leave the normalmap on as it still @@ -5547,6 +5744,7 @@ void RSurf_ActiveWorldEntity(void) VectorSet(rsurface.modellight_lightdir, 0, 0, 1); VectorSet(rsurface.colormap_pantscolor, 0, 0, 0); VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0); + VectorSet(rsurface.glowmod, 1, 1, 1); memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend)); rsurface.frameblend[0].lerp = 1; rsurface.basepolygonfactor = r_refdef.polygonfactor; @@ -5618,6 +5816,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir); VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor); VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor); + VectorCopy(ent->glowmod, rsurface.glowmod); memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend)); rsurface.basepolygonfactor = r_refdef.polygonfactor; rsurface.basepolygonoffset = r_refdef.polygonoffset; @@ -7465,6 +7664,12 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; Matrix4x4_Transform(&rsurface.matrix, tempcenter, center); + if (queueentity->transparent_offset) // transparent offset + { + center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset; + center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset; + center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset; + } R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight); } }