#include "polygon.h"
#include "image.h"
#include "ft2.h"
+#include "csprogs.h"
+#include "cl_video.h"
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
+cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
+cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
rtexture_t *r_texture_whitecube;
rtexture_t *r_texture_normalizationcube;
rtexture_t *r_texture_fogattenuation;
+rtexture_t *r_texture_fogheighttexture;
rtexture_t *r_texture_gammaramps;
unsigned int r_texture_gammaramps_serial;
//rtexture_t *r_texture_fogintensity;
r_refdef.fog_end = 16384;
r_refdef.fog_height = 1<<30;
r_refdef.fog_fadedepth = 128;
+ memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
}
static void R_BuildBlankTextures(void)
}
}
+static void R_BuildFogHeightTexture(void)
+{
+ unsigned char *inpixels;
+ int size;
+ int x;
+ int y;
+ int j;
+ float c[4];
+ float f;
+ inpixels = NULL;
+ strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
+ if (r_refdef.fogheighttexturename[0])
+ inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
+ if (!inpixels)
+ {
+ r_refdef.fog_height_tablesize = 0;
+ if (r_texture_fogheighttexture)
+ R_FreeTexture(r_texture_fogheighttexture);
+ r_texture_fogheighttexture = NULL;
+ if (r_refdef.fog_height_table2d)
+ Mem_Free(r_refdef.fog_height_table2d);
+ r_refdef.fog_height_table2d = NULL;
+ if (r_refdef.fog_height_table1d)
+ Mem_Free(r_refdef.fog_height_table1d);
+ r_refdef.fog_height_table1d = NULL;
+ return;
+ }
+ size = image_width;
+ r_refdef.fog_height_tablesize = size;
+ r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
+ r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
+ memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
+ Mem_Free(inpixels);
+ // LordHavoc: now the magic - what is that table2d for? it is a cooked
+ // average fog color table accounting for every fog layer between a point
+ // and the camera. (Note: attenuation is handled separately!)
+ for (y = 0;y < size;y++)
+ {
+ for (x = 0;x < size;x++)
+ {
+ Vector4Clear(c);
+ f = 0;
+ if (x < y)
+ {
+ for (j = x;j <= y;j++)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ else
+ {
+ for (j = x;j >= y;j--)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ f = 1.0f / f;
+ r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
+ }
+ }
+ r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
+}
+
//=======================================================================================================================================================
static const char *builtinshaderstring =
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#endif\n"
"//uncomment these if you want to use them:\n"
"uniform vec4 UserVec1;\n"
-"// uniform vec4 UserVec2;\n"
+"uniform vec4 UserVec2;\n"
"// uniform vec4 UserVec3;\n"
"// uniform vec4 UserVec4;\n"
"// uniform float ClientTime;\n"
"#ifdef USEPOSTPROCESSING\n"
"// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
"// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
+" float sobel = 1.0;\n"
+" // vec2 ts = textureSize(Texture_First, 0);\n"
+" // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
+" vec2 px = PixelSize;\n"
+" vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
+" vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
+" vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
+" vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
+" vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
+" vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
+" vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
+" vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
+" vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
+" vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
+" vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
+" vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
+" float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
+" float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
+" float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
+" float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
+" float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
+" float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
+" float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
+" float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
+" float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
+" float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
+" float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
+" float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
+" sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
-" gl_FragColor /= (1 + 5 * UserVec1.y);\n"
+" gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
+" gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
"#endif\n"
"\n"
"#ifdef USESATURATION\n"
"uniform sampler2D Texture_Shirt;\n"
"#endif\n"
"#ifdef USEFOG\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+"uniform sampler2D Texture_FogHeightTexture;\n"
+"#endif\n"
"uniform sampler2D Texture_FogMask;\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"uniform float FogRangeRecip;\n"
"uniform float FogPlaneViewDist;\n"
"uniform float FogHeightFade;\n"
-"float FogVertex(void)\n"
+"vec3 FogVertex(vec3 surfacecolor)\n"
"{\n"
" vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
" float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+" vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
+" fogfrac = fogheightpixel.a;\n"
+" return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
+"# ifdef USEFOGOUTSIDE\n"
+" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"# endif\n"
+" return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
-" return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
"}\n"
"#endif\n"
"\n"
"vec4 GetShadowMapTCCube(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= myhalf(FogVertex());\n"
-"#else\n"
-" color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
+"#if defined(USEREFLECTION)\n"
+"#undef USESHADOWMAPORTHO\n"
+"#endif\n"
+"\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
+"#endif\n"
+"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
"#ifdef VERTEX_SHADER\n"
"void main\n"
"#ifdef FRAGMENT_SHADER\n"
"\n"
"#ifdef USEFOG\n"
-"float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
+"float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
"{\n"
" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+" float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
+" fogfrac = fogheightpixel.a;\n"
+" return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
+"# ifdef USEFOGOUTSIDE\n"
+" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"# endif\n"
+" return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
-" return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
"}\n"
"#endif\n"
"\n"
" float3 adir = abs(dir);\n"
" float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-" return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+" return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
"# else\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
"}\n"
"# endif\n"
"# endif\n"
-"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
+"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"#ifdef USESHADOWMAPCUBE\n"
"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\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, ivec2(x, y))\n"
+"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
"# else\n"
-"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
-"# endif\n"
-" float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
-"# if USESHADOWMAPPCF > 1\n"
-" float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
-" float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
-" float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
-" float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
-" float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
-" float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
-" float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
-" float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
-" float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
-" float4 locols = float4(group1.ab, group3.ab);\n"
-" float4 hicols = float4(group7.rg, group9.rg);\n"
-" locols.yz += group2.ab;\n"
-" hicols.yz += group8.rg;\n"
-" float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
-" float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
-" lerp(locols, hicols, offset.y);\n"
-" float4 cols = group5 + float4(group2.rg, group8.ab);\n"
-" cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
-" f = dot(cols, float4(1.0/25.0));\n"
-"# else\n"
-" float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
-" float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
-" float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
-" float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
-" float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
-" lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
-" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
"# endif\n"
+" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
+" float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
+" float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
+" float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
+" float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
+" lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
+" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
"# else\n"
"# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
"# if USESHADOWMAPPCF > 1\n"
"uniform sampler2D Texture_ScreenDepth,\n"
"uniform sampler2D Texture_ScreenNormalMap,\n"
"\n"
+"#ifdef USECUBEFILTER\n"
+"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"uniform samplerRECTShadow Texture_ShadowMapRect,\n"
"{\n"
" // calculate viewspace pixel position\n"
" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-" ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
+" //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
" float3 position;\n"
" position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"out float3 ShadowMapTC : TEXCOORD8,\n"
+"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"out float4 gl_Position : POSITION\n"
")\n"
"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"float3 ShadowMapTC : TEXCOORD8,\n"
+"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"\n"
"uniform sampler2D Texture_Normal,\n"
"uniform sampler2D Texture_Shirt,\n"
"#endif\n"
"#ifdef USEFOG\n"
+"uniform sampler2D Texture_FogHeightTexture,\n"
"uniform sampler2D Texture_FogMask,\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#else\n"
-" color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
- SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
- SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
- SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
- SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
- SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
+ SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
+ SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
+ SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+ SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+ SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESATURATION\n", " saturation"},
{"#define USEFOGINSIDE\n", " foginside"},
{"#define USEFOGOUTSIDE\n", " fogoutside"},
+ {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
int loc_Texture_SecondaryGlow;
int loc_Texture_Pants;
int loc_Texture_Shirt;
+ int loc_Texture_FogHeightTexture;
int loc_Texture_FogMask;
int loc_Texture_Lightmap;
int loc_Texture_Deluxemap;
p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
+ if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
CGparameter fp_Texture_SecondaryGlow;
CGparameter fp_Texture_Pants;
CGparameter fp_Texture_Shirt;
+ CGparameter fp_Texture_FogHeightTexture;
CGparameter fp_Texture_FogMask;
CGparameter fp_Texture_Lightmap;
CGparameter fp_Texture_Deluxemap;
p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
+ p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
// distorted background
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
mode = SHADERMODE_WATER;
- else
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
mode = SHADERMODE_REFRACTION;
+ else
+ {
+ mode = SHADERMODE_GENERIC;
+ permutation |= SHADERPERMUTATION_DIFFUSE;
+ }
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+ if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ReflectCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
R_BuildNormalizationCube();
}
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
//r_texture_fogintensity = NULL;
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_size = 0;
if (cl.worldmodel)
{
- strlcpy(entname, cl.worldmodel->name, sizeof(entname));
- l = (int)strlen(entname) - 4;
- if (l >= 0 && !strcmp(entname + l, ".bsp"))
+ dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
+ if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
{
- memcpy(entname + l, ".ent", 5);
- if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
- {
- CL_ParseEntityLump(entities);
- Mem_Free(entities);
- return;
- }
+ CL_ParseEntityLump(entities);
+ Mem_Free(entities);
+ return;
}
if (cl.worldmodel->brush.entities)
CL_ParseEntityLump(cl.worldmodel->brush.entities);
Cvar_RegisterVariable(&r_showdisabledepthtest);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_drawentities);
+ Cvar_RegisterVariable(&r_drawworld);
Cvar_RegisterVariable(&r_cullentities_trace);
Cvar_RegisterVariable(&r_cullentities_trace_samples);
Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
Cvar_RegisterVariable(&r_cullentities_trace_delay);
Cvar_RegisterVariable(&r_drawviewmodel);
+ Cvar_RegisterVariable(&r_drawexteriormodel);
Cvar_RegisterVariable(&r_speeds);
Cvar_RegisterVariable(&r_fullbrights);
Cvar_RegisterVariable(&r_wateralpha);
entity_render_t *ent;
vec3_t tempdiffusenormal, avg;
vec_t f, fa, fd, fdd;
- qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
+ qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
for (i = 0;i < r_refdef.scene.numentities;i++)
{
: RENDER_EXTERIORMODEL;
if (!r_drawviewmodel.integer)
renderimask |= RENDER_VIEWMODEL;
+ if (!r_drawexteriormodel.integer)
+ renderimask |= RENDER_EXTERIORMODEL;
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
- if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
+ if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
+ // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
{
for (i = 0;i < r_refdef.scene.numentities;i++)
{
GL_CullFace(r_refdef.view.cullface_back);
}
+/*
+================
+R_RenderView_UpdateViewVectors
+================
+*/
+static void R_RenderView_UpdateViewVectors(void)
+{
+ // break apart the view matrix into vectors for various purposes
+ // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+ // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+ VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // make an inverted copy of the view matrix for tracking sprites
+ Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+}
+
void R_RenderScene(void);
void R_RenderWaterPlanes(void);
static void R_Water_StartFrame(void)
{
int i;
- int waterwidth, waterheight, texturewidth, textureheight;
+ int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
// calculate desired texture sizes
// can't use water if the card does not support the texture size
if (!r_water.integer || r_showsurfaces.integer)
- texturewidth = textureheight = waterwidth = waterheight = 0;
+ texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
else if (vid.support.arb_texture_non_power_of_two)
{
texturewidth = waterwidth;
textureheight = waterheight;
+ camerawidth = waterwidth;
+ cameraheight = waterheight;
}
else
{
for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
+ for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
+ for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
}
// allocate textures as needed
- if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
+ if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
{
r_waterstate.maxwaterplanes = MAX_WATERPLANES;
for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
if (p->texture_reflection)
R_FreeTexture(p->texture_reflection);
p->texture_reflection = NULL;
+ if (p->texture_camera)
+ R_FreeTexture(p->texture_camera);
+ p->texture_camera = NULL;
}
memset(&r_waterstate, 0, sizeof(r_waterstate));
r_waterstate.texturewidth = texturewidth;
r_waterstate.textureheight = textureheight;
+ r_waterstate.camerawidth = camerawidth;
+ r_waterstate.cameraheight = cameraheight;
}
if (r_waterstate.texturewidth)
vec3_t normal;
vec3_t center;
mplane_t plane;
+ int cam_ent;
r_waterstate_waterplane_t *p;
texture_t *t = R_GetCurrentTexture(surface->texture);
+ cam_ent = t->camera_entity;
+ if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
+ cam_ent = 0;
+
// just use the first triangle with a valid normal for any decisions
VectorClear(normal);
for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
// find a matching plane if there is one
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
- if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
- break;
+ if(p->camera_entity == t->camera_entity)
+ if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
+ break;
if (planeindex >= r_waterstate.maxwaterplanes)
return; // nothing we can do, out of planes
// clear materialflags and pvs
p->materialflags = 0;
p->pvsvalid = false;
+ p->camera_entity = t->camera_entity;
}
// merge this surface's materialflags into the waterplane
p->materialflags |= t->currentmaterialflags;
- // merge this surface's PVS into the waterplane
- VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
- if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
- && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ if(!(p->materialflags & MATERIALFLAG_CAMERA))
{
- r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
- p->pvsvalid = true;
+ // merge this surface's PVS into the waterplane
+ VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
+ if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
+ && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ {
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
+ p->pvsvalid = true;
+ }
}
}
r_refdef_view_t myview;
int planeindex;
r_waterstate_waterplane_t *p;
+ vec3_t visorigin;
originalview = r_refdef.view;
if (!p->texture_refraction)
goto error;
}
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ if (!p->texture_camera)
+ p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
+ if (!p->texture_camera)
+ goto error;
+ }
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
{
r_waterstate.renderingrefraction = true;
r_refdef.view = myview;
+
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ R_RenderView_UpdateViewVectors();
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ }
+
PlaneClassify(&r_refdef.view.clipplane);
R_ResetViewRendering3D();
R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
r_waterstate.renderingrefraction = false;
}
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ r_refdef.view = myview;
+
+ r_refdef.view.clipplane = p->plane;
+ VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
+ r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ r_refdef.view.width = r_waterstate.camerawidth;
+ r_refdef.view.height = r_waterstate.cameraheight;
+ r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
+ r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
+
+ if(p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ }
+
+ // reverse the cullface settings for this render
+ r_refdef.view.cullface_front = GL_FRONT;
+ r_refdef.view.cullface_back = GL_BACK;
+ // also reverse the view matrix
+ Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
+ R_RenderView_UpdateViewVectors();
+ if(p->camera_entity)
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+
+ // camera needs no clipplane
+ r_refdef.view.useclipplane = false;
+
+ PlaneClassify(&r_refdef.view.clipplane);
+
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
+ R_RenderScene();
+
+ R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_waterstate.renderingrefraction = false;
+ }
}
r_waterstate.renderingscene = false;
cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
// apply the blur
- if (cl.motionbluralpha > 0)
+ if (cl.motionbluralpha > 0 && !r_refdef.envmap)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(1, 1, 1, cl.motionbluralpha);
r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
+ if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
+ R_BuildFogHeightTexture();
// fog color was already set
// update the fog texture
if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
R_BuildFogTexture();
+ r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
+ r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
}
else
r_refdef.fogenabled = false;
return;
}
- if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
+ if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
r_refdef.view.colorscale = r_hdr_scenebrightness.value;
- // break apart the view matrix into vectors for various purposes
- // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
- // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
- Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
- VectorNegate(r_refdef.view.left, r_refdef.view.right);
- // make an inverted copy of the view matrix for tracking sprites
- Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+ R_RenderView_UpdateViewVectors();
R_Shadow_UpdateWorldLightSelection();
R_TimeReport("modeldepth");
}
- if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
+ if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadowMaps();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
t->update_lastrenderframe = r_textureframe;
t->update_lastrenderentity = (void *)ent;
+ if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
+ t->camera_entity = ent->entitynumber;
+ else
+ t->camera_entity = 0;
+
// switch to an alternate material if this is a q1bsp animated material
{
texture_t *texture = t;
if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
t->currentalpha *= t->r_water_wateralpha;
if(!r_waterstate.enabled || r_refdef.view.isoverlay)
- t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
+ t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
if (!(rsurface.ent_flags & RENDER_LIGHT))
t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
{
- if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
+ if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
}
else
- t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
+ t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
else if (r_batchmode.integer == 2)
{
- #define MAXBATCHTRIANGLES 4096
+ #define MAXBATCHTRIANGLES 65536
int batchtriangles = 0;
static int batchelements[MAXBATCHTRIANGLES*3];
for (i = 0;i < texturenumsurfaces;i = j)
bestp = NULL;
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
{
+ if(p->camera_entity != rsurface.texture->camera_entity)
+ continue;
d = 0;
for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
{
{
case RENDERPATH_CGGL:
#ifdef SUPPORTCG
- if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
- if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
+ else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
+ if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
#endif
break;
case RENDERPATH_GL20:
if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
+ else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
break;
case RENDERPATH_GL13:
}
else if (r_batchmode.integer == 2)
{
-#define MAXBATCHTRIANGLES 4096
int batchtriangles = 0;
static int batchelements[MAXBATCHTRIANGLES*3];
for (i = 0;i < texturenumsurfaces;i = j)
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
+ if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
return;
RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
if (prepass)
R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
- else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
+ else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
{
// render water or distortion background, then blend surface on top
GL_DepthMask(true);