#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)"};
cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
+cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
+cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
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", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
+cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
+
cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
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;
+rtexture_t *r_texture_reflectcube;
+
+// TODO: hash lookups?
+typedef struct cubemapinfo_s
+{
+ char basename[64];
+ rtexture_t *texture;
+}
+cubemapinfo_t;
+
+int r_texture_numcubemaps;
+cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
unsigned int r_queries[MAX_OCCLUSION_QUERIES];
unsigned int r_numqueries;
0, 1, 0
};
-extern void R_DrawModelShadows(void);
-
void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
{
int i;
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"
"#define USELIGHTMAP\n"
"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
+"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\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"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
" vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
" // FIXME temporary hack to detect the case that the reflection\n"
" // gets blackened at edges due to leaving the area that contains actual\n"
"varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
"#endif\n"
"\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
"varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
"varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
"#endif\n"
"uniform vec4 FogPlane;\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"varying vec3 ShadowMapTC;\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"\n"
"uniform sampler2D Texture_Normal;\n"
"uniform sampler2D Texture_Color;\n"
-"//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"uniform sampler2D Texture_Gloss;\n"
-"//#endif\n"
"#ifdef USEGLOW\n"
"uniform sampler2D Texture_Glow;\n"
"#endif\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"uniform sampler2D Texture_SecondaryNormal;\n"
"uniform sampler2D Texture_SecondaryColor;\n"
-"//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"uniform sampler2D Texture_SecondaryGloss;\n"
-"//#endif\n"
"#ifdef USEGLOW\n"
"uniform sampler2D Texture_SecondaryGlow;\n"
"#endif\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"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
"uniform sampler2D Texture_Attenuation;\n"
"uniform samplerCube Texture_Cube;\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"#endif\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
+"# else\n"
+"# ifdef USESHADOWMAPVSDCT\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" vec2 tc;\n"
-" vec2 offset;\n"
-" float ma;\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z) // X\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 // Z\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) // Y\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 // Z\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"
-"\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"
-" return stc;\n"
+" vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
+" vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
+" return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
-"# else\n"
+"# else\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\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"
-" return stc;\n"
+" float ma = adir.z;\n"
+" vec4 proj = vec4(dir, 2.5);\n"
+" if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
+" if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
+" vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
+" return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
+"# endif\n"
"# endif\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\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"
"# endif\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\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"
+" vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
+"# if USESHADOWMAPPCF > 1\n"
+" vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
+" vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
+" vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
+" vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
+" vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
+" vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
+" vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
+" vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
+" vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
+" vec4 locols = vec4(group1.ab, group3.ab);\n"
+" vec4 hicols = vec4(group7.rg, group9.rg);\n"
+" locols.yz += group2.ab;\n"
+" hicols.yz += group8.rg;\n"
+" vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
+" vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
+" mix(locols, hicols, offset.y);\n"
+" vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
+" cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
+" f = dot(cols, vec4(1.0/25.0));\n"
+"# else\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 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"
+"# endif\n"
"# else\n"
"# ifdef GL_EXT_gpu_shader4\n"
"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
"# endif\n"
"# endif\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
" return f;\n"
"}\n"
"# endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
"#endif // FRAGMENT_SHADER\n"
"\n"
"\n"
"\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
" vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
+" float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
"#else\n"
" vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
+" float a = texture2D(Texture_Gloss, TexCoord).a;\n"
"#endif\n"
"\n"
-" gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
+" gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#else // !MODE_DEFERREDGEOMETRY\n"
" // calculate directional shading\n"
" vec3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
"# else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
"# endif\n"
"#endif\n"
"\n"
"#ifdef MODE_LIGHTSOURCE\n"
"uniform mat4 ModelToLight;\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform mat4 ShadowMapMatrix;\n"
+"#endif\n"
"void main(void)\n"
"{\n"
"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
" EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
"#endif\n"
"\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
" VectorS = gl_MultiTexCoord1.xyz;\n"
" VectorT = gl_MultiTexCoord2.xyz;\n"
" VectorR = gl_MultiTexCoord3.xyz;\n"
" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
+"#endif\n"
+"\n"
"#ifdef USEREFLECTION\n"
" ModelViewProjectionPosition = gl_Position;\n"
"#endif\n"
"uniform vec4 ScreenCenterRefractReflect;\n"
"uniform myhalf4 ReflectColor;\n"
"#endif\n"
+"#ifdef USEREFLECTCUBE\n"
+"uniform mat4 ModelToReflectCube;\n"
+"uniform sampler2D Texture_ReflectMask;\n"
+"uniform samplerCube Texture_ReflectCube;\n"
+"#endif\n"
"#ifdef MODE_LIGHTDIRECTION\n"
"uniform myhalf3 LightColor;\n"
"#endif\n"
" myhalf3 diffusetex = color.rgb;\n"
"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
+" myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
"# else\n"
-" myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
+" myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USEREFLECTCUBE\n"
+" vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
+" vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
+" vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
+" diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
"#ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"#else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"#endif\n"
-" color.rgb += glosstex * (specular * Color_Specular);\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
"#else\n"
" color.rgb = diffusetex * Color_Ambient;\n"
" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"# else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"# endif\n"
-" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
+" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"# endif\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
+"#endif\n"
+"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
" vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
" color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
-" color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+" color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
"#endif\n"
"\n"
"#ifdef USEGLOW\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 USELIGHTMAP\n"
"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
+"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\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"
"}\n"
"#endif // USEOFFSETMAPPING\n"
"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
-"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
-"{\n"
-" float3 adir = abs(dir);\n"
-" float2 tc;\n"
-" float2 offset;\n"
-" float ma;\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z) // X\n"
-" {\n"
-" ma = adir.x;\n"
-" tc = dir.zy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (adir.y > adir.z) // Y\n"
-" {\n"
-" ma = adir.y;\n"
-" tc = dir.xz;\n"
-" offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-"\n"
-" float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += offset * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
-"}\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
"# else\n"
+"# ifdef USESHADOWMAPVSDCT\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\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"
-" float ma = max(max(adir.x, adir.y), adir.z);\n"
-" float3 stc = float3(lerp(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"
-" return stc;\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"
+" float3 adir = abs(dir);\n"
+" float ma = adir.z;\n"
+" float4 proj = float4(dir, 2.5);\n"
+" if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
+" if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
+" float2 aparams = ShadowMap_Parameters.xy / ma;\n"
+" return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+"}\n"
+"# endif\n"
"# endif\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\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"
"# endif\n"
"\n"
"# endif\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
" f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
"# endif\n"
"# endif\n"
-" return f;\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
+" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
"#ifdef USEALPHAKILL\n"
"uniform sampler2D Texture_Color,\n"
"#endif\n"
+"uniform sampler2D Texture_Gloss,\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"uniform sampler2D Texture_SecondaryNormal,\n"
+"uniform sampler2D Texture_SecondaryGloss,\n"
"#endif\n"
"#ifdef USEOFFSETMAPPING\n"
"uniform float OffsetMapping_Scale,\n"
"\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
" float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
+" float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
"#else\n"
" float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
+" float a = tex2D(Texture_Gloss, TexCoord).a;\n"
"#endif\n"
"\n"
" gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 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"
" // calculate directional shading\n"
" float3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
"# else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
"# endif\n"
"#endif\n"
"\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
"uniform float3 LightPosition,\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform float4x4 ShadowMapMatrix,\n"
+"#endif\n"
"\n"
"out float4 gl_FrontColor : COLOR,\n"
"out float4 TexCoordBoth : TEXCOORD0,\n"
"out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
-"out float3 LightVector : TEXCOORD5,\n"
+"out float3 LightVector : TEXCOORD1,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
"out float3 CubeVector : TEXCOORD3,\n"
"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
"out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
+"#endif\n"
"out float4 gl_Position : POSITION\n"
")\n"
"{\n"
" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
+"#endif\n"
+"\n"
"#ifdef USEREFLECTION\n"
" ModelViewProjectionPosition = gl_Position;\n"
"#endif\n"
"float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
-"float3 LightVector : TEXCOORD5,\n"
+"float3 LightVector : TEXCOORD1,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
"float3 CubeVector : TEXCOORD3,\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
"float4 ModelViewPosition : TEXCOORD0,\n"
"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
"float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
+"#endif\n"
"\n"
"uniform sampler2D Texture_Normal,\n"
"uniform sampler2D Texture_Color,\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"
"uniform float4 ScreenCenterRefractReflect,\n"
"uniform half4 ReflectColor,\n"
"#endif\n"
+"#ifdef USEREFLECTCUBE\n"
+"uniform float4x4 ModelToReflectCube,\n"
+"uniform sampler2D Texture_ReflectMask,\n"
+"uniform samplerCUBE Texture_ReflectCube,\n"
+"#endif\n"
"#ifdef MODE_LIGHTDIRECTION\n"
"uniform half3 LightColor,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
"uniform sampler2D Texture_Attenuation,\n"
"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"uniform float2 ShadowMap_TextureScale,\n"
"uniform float4 ShadowMap_Parameters,\n"
"#endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
"\n"
"out float4 gl_FragColor : COLOR\n"
")\n"
" half3 diffusetex = color.rgb;\n"
"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
+" half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
"# else\n"
-" half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
+" half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USEREFLECTCUBE\n"
+" float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
+" float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
+" float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
+" diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
"#ifdef USEEXACTSPECULARMATH\n"
-" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"#else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"#endif\n"
-" color.rgb += glosstex * (specular * Color_Specular);\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
"#else\n"
" color.rgb = diffusetex * Color_Ambient;\n"
" half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"# else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"# endif\n"
-" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
+" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"# endif\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
+"# if defined(USESHADOWMAP2D)\n"
+"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
+"# endif\n"
+"# if defined(USESHADOWMAPRECT)\n"
+"Texture_ShadowMapRect, ShadowMap_Parameters\n"
+"# endif\n"
+" );\n"
+"#endif\n"
+"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
" color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
-" color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+" color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
"#endif\n"
"\n"
"#ifdef USEGLOW\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"
"#endif // !MODE_DEPTH_OR_SHADOW\n"
;
+char *glslshaderstring = NULL;
+char *cgshaderstring = NULL;
+
//=======================================================================================================================================================
typedef struct shaderpermutationinfo_s
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_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 26 ///< 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"},
{"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
{"#define USESHADOWSAMPLER\n", " shadowsampler"},
{"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
+ {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
{"#define USEALPHAKILL\n", " alphakill"},
+ {"#define USEREFLECTCUBE\n", " reflectcube"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
{
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
- {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+ {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
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;
int loc_Texture_ScreenNormalMap;
int loc_Texture_ScreenDiffuse;
int loc_Texture_ScreenSpecular;
+ int loc_Texture_ReflectMask;
+ int loc_Texture_ReflectCube;
int loc_Alpha;
int loc_BloomBlur_Parameters;
int loc_ClientTime;
int loc_ModelViewProjectionMatrix;
int loc_ModelViewMatrix;
int loc_PixelToScreenTexCoord;
+ int loc_ModelToReflectCube;
+ int loc_ShadowMapMatrix;
}
r_glsl_permutation_t;
char *shaderstring;
if (!filename || !filename[0])
return NULL;
+ if (!strcmp(filename, "glsl/default.glsl"))
+ {
+ if (!glslshaderstring)
+ {
+ glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+ if (glslshaderstring)
+ Con_DPrintf("Loading shaders from file %s...\n", filename);
+ else
+ glslshaderstring = (char *)builtinshaderstring;
+ }
+ shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
+ memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
+ return shaderstring;
+ }
shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
if (shaderstring)
{
Con_DPrintf("from disk %s... ", filename);
return shaderstring;
}
- else if (!strcmp(filename, "glsl/default.glsl"))
- {
- shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
- memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
- }
return shaderstring;
}
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");
p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
+ p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
+ p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
+ p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
+ p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
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);
if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
- if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
+ if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : 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_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
+ if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
+ if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
CHECKGLERROR
Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
}
}
if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+ if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
}
#ifdef SUPPORTCG
CGparameter vp_BackgroundTexMatrix;
CGparameter vp_ModelViewProjectionMatrix;
CGparameter vp_ModelViewMatrix;
+ CGparameter vp_ShadowMapMatrix;
CGparameter fp_Texture_First;
CGparameter fp_Texture_Second;
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;
CGparameter fp_Texture_ScreenNormalMap;
CGparameter fp_Texture_ScreenDiffuse;
CGparameter fp_Texture_ScreenSpecular;
+ CGparameter fp_Texture_ReflectMask;
+ CGparameter fp_Texture_ReflectCube;
CGparameter fp_Alpha;
CGparameter fp_BloomBlur_Parameters;
CGparameter fp_ClientTime;
CGparameter fp_ViewTintColor;
CGparameter fp_ViewToLight;
CGparameter fp_PixelToScreenTexCoord;
+ CGparameter fp_ModelToReflectCube;
}
r_cg_permutation_t;
char *shaderstring;
if (!filename || !filename[0])
return NULL;
+ if (!strcmp(filename, "cg/default.cg"))
+ {
+ if (!cgshaderstring)
+ {
+ cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+ if (cgshaderstring)
+ Con_DPrintf("Loading shaders from file %s...\n", filename);
+ else
+ cgshaderstring = (char *)builtincgshaderstring;
+ }
+ shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
+ memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
+ return shaderstring;
+ }
shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
if (shaderstring)
{
Con_DPrintf("from disk %s... ", filename);
return shaderstring;
}
- else if (!strcmp(filename, "cg/default.cg"))
- {
- shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
- memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
- }
return shaderstring;
}
+static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
+{
+ // TODO: load or create .fp and .vp shader files
+}
+
static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
{
int i;
const char *geomstrings_list[32+3];
const char *fragstrings_list[32+3];
char permutationname[256];
+ char cachename[256];
CGprofile vertexProfile;
CGprofile fragmentProfile;
p->fprogram = NULL;
permutationname[0] = 0;
+ cachename[0] = 0;
vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
+ strlcat(cachename, "cg/", sizeof(cachename));
// the first pretext is which type of shader to compile as
// (later these will all be bound together as a program object)
geomstrings_list[geomstrings_count++] = modeinfo->pretext;
fragstrings_list[fragstrings_count++] = modeinfo->pretext;
strlcat(permutationname, modeinfo->name, sizeof(permutationname));
+ strlcat(cachename, modeinfo->name, sizeof(cachename));
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
+ strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
}
else
{
}
}
+ // replace spaces in the cachename with _ characters
+ for (i = 0;cachename[i];i++)
+ if (cachename[i] == ' ')
+ cachename[i] = '_';
+
// now append the shader text itself
vertstrings_list[vertstrings_count++] = vertexstring;
geomstrings_list[geomstrings_count++] = geometrystring;
//cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
CHECKGLERROR
- // compile the vertex program
- if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
+ // try to load the cached shader, or generate one
+ R_CG_CacheShader(p, cachename, vertstring, fragstring);
+
+ // if caching failed, do a dynamic compile for now
+ CHECKCGERROR
+ if (vertstring[0] && !p->vprogram)
+ p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
+ CHECKCGERROR
+ if (fragstring[0] && !p->fprogram)
+ p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
+ CHECKCGERROR
+
+ // look up all the uniform variable names we care about, so we don't
+ // have to look them up every time we set them
+ if (p->vprogram)
{
CHECKCGERROR
-#if 0
- cgCompileProgram(p->vprogram);CHECKCGERROR
- if (!cgIsProgramCompiled(p->vprogram))
- {
- CHECKCGERROR
- cgDestroyProgram(p->vprogram);CHECKCGERROR
- p->vprogram = 0;
- }
- else
-#endif
- {
- cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
- cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
- // look up all the uniform variable names we care about, so we don't
- // have to look them up every time we set them
- CHECKCGERROR
- p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
- p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
- p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
- p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
- p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
- p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
- p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
- p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
- p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
- CHECKCGERROR
- }
+ cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
+ p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
+ p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
+ p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
+ p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
+ p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
+ p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
+ p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
+ p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
+ p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
+ p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
+ CHECKCGERROR
}
-
- // compile the fragment program
- if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
+ if (p->fprogram)
{
-#if 0
- cgCompileProgram(p->fprogram);CHECKCGERROR
- if (!cgIsProgramCompiled(p->fprogram))
- {
- CHECKCGERROR
- cgDestroyProgram(p->fprogram);CHECKCGERROR
- p->fprogram = 0;
- }
- else
-#endif
- {
- cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
- cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
- CHECKCGERROR
- p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
- p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
- p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
- p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
- p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
- p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
- p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
- p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
- p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
- p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
- 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_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
- p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
- p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
- p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
- p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
- p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
- p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
- p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
- p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
- p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
- p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
- p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
- p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
- p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
- p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
- p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
- p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
- p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
- p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
- p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
- p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
- p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
- p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
- p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
- p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
- p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
- p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
- p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
- p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
- p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
- p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
- p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
- p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
- p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
- p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
- p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
- p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
- p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
- p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
- p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
- p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
- p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
- p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
- p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
- p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
- p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
- p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
- p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
- p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
- p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
- p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
- p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
- p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
- p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
- p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
- p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
- p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
- p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
- p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
- CHECKCGERROR
- }
+ CHECKCGERROR
+ cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
+ p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
+ p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
+ p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
+ p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
+ p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
+ p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
+ p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
+ p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
+ p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
+ p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
+ 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");
+ p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
+ p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
+ p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
+ p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
+ p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
+ p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
+ p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
+ p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
+ p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
+ p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
+ p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
+ p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
+ p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
+ p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
+ p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
+ p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
+ p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
+ p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
+ p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
+ p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
+ p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
+ p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
+ p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
+ p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
+ p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
+ p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
+ p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
+ p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
+ p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
+ p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
+ p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
+ p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
+ p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
+ p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
+ p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
+ p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
+ p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
+ p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
+ p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
+ p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
+ p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
+ p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
+ p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
+ p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
+ p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
+ p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
+ p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
+ p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
+ p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
+ p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
+ p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
+ p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
+ p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
+ p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
+ p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
+ p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
+ p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
+ p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
+ p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
+ CHECKCGERROR
}
if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
CHECKCGERROR
if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
+ if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
}
void CG_BindTexture(CGparameter param, rtexture_t *tex)
void R_GLSL_Restart_f(void)
{
unsigned int i, limit;
+ if (glslshaderstring && glslshaderstring != builtinshaderstring)
+ Mem_Free(glslshaderstring);
+ glslshaderstring = NULL;
+ if (cgshaderstring && cgshaderstring != builtincgshaderstring)
+ Mem_Free(cgshaderstring);
+ cgshaderstring = NULL;
switch(vid.renderpath)
{
case RENDERPATH_GL20:
extern qboolean r_shadow_usingshadowmaprect;
extern qboolean r_shadow_usingshadowmapcube;
extern qboolean r_shadow_usingshadowmap2d;
+extern qboolean r_shadow_usingshadowmaportho;
extern float r_shadow_shadowmap_texturescale[2];
extern float r_shadow_shadowmap_parameters[4];
extern qboolean r_shadow_shadowmapvsdct;
extern rtexture_t *r_shadow_shadowmap2dtexture;
extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
extern rtexture_t *r_shadow_shadowmapvsdcttexture;
+extern matrix4x4_t r_shadow_shadowmapmatrix;
extern int r_shadow_shadowmaplod; // changes for each light based on distance
extern int r_shadow_prepass_width;
extern int r_shadow_prepass_height;
// 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);
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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)
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
}
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
{
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
{
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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))
+ {
+ permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
{
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
{
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
{
// deluxemapping (light direction texture)
{
case RENDERPATH_GL20:
R_SetupShader_SetPermutationGLSL(mode, permutation);
+ if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
if (mode == SHADERMODE_LIGHTSOURCE)
{
if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
// 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_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]);
if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
}
else
}
if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
+ if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
+ 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]);
+
if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
- if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
+ if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
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_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
- if (rsurface.rtlight)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
- if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
- if (r_shadow_usingshadowmapcube)
- if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
- if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
+ if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
+ if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
+ if (rsurface.rtlight)
+ {
+ if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
+ if (r_shadow_usingshadowmapcube)
+ if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
+ if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
+ }
}
CHECKGLERROR
break;
case RENDERPATH_CGGL:
#ifdef SUPPORTCG
R_SetupShader_SetPermutationCG(mode, permutation);
+ if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
if (mode == SHADERMODE_LIGHTSOURCE)
{
if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
}
if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
+ if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
CHECKGLERROR
// additive passes are only darkened by fog, not tinted
if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
- if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
- if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
}
else
if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
}
+ if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
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
if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
- if (rsurface.rtlight)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
- if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
- if (r_shadow_usingshadowmapcube)
- if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
- if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
+ if (rsurface.rtlight)
+ {
+ if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
+ if (r_shadow_usingshadowmapcube)
+ if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
+ }
}
CHECKGLERROR
R_PurgeTexture(s->gloss );s->gloss = NULL;
R_PurgeTexture(s->glow );s->glow = NULL;
R_PurgeTexture(s->fog );s->fog = NULL;
+ R_PurgeTexture(s->reflect);s->reflect = NULL;
s->loadsequence = 0;
}
}
// check for DDS texture file first
if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
{
- basepixels = loadimagepixelsbgra(name, complain, true);
+ basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
if (basepixels == NULL)
return NULL;
}
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
if (ddsbase)
skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
+ skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
}
// _norm is the name used by tenebrae and has been adopted as standard
if (r_loadnormalmap && skinframe->nmap == NULL)
{
- if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
+ if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
{
skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
pixels = NULL;
}
- else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
+ else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
// _luma is supported only for tenebrae compatibility
// _glow is the preferred name
- if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
+ if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
{
skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
Mem_Free(pixels);pixels = NULL;
}
- if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
+ if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
pixels = NULL;
}
- if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
+ if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
pixels = NULL;
}
- if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
+ if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
pixels = NULL;
}
+ if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ {
+ skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
+ R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
+ Mem_Free(pixels);
+ pixels = NULL;
+ }
+
if (basepixels)
Mem_Free(basepixels);
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
skinframe->avgcolor[0] = rand() / RAND_MAX;
return skinframe;
}
+//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
+typedef struct suffixinfo_s
+{
+ char *suffix;
+ qboolean flipx, flipy, flipdiagonal;
+}
+suffixinfo_t;
+static suffixinfo_t suffix[3][6] =
+{
+ {
+ {"px", false, false, false},
+ {"nx", false, false, false},
+ {"py", false, false, false},
+ {"ny", false, false, false},
+ {"pz", false, false, false},
+ {"nz", false, false, false}
+ },
+ {
+ {"posx", false, false, false},
+ {"negx", false, false, false},
+ {"posy", false, false, false},
+ {"negy", false, false, false},
+ {"posz", false, false, false},
+ {"negz", false, false, false}
+ },
+ {
+ {"rt", true, false, true},
+ {"lf", false, true, true},
+ {"ft", true, true, false},
+ {"bk", false, false, false},
+ {"up", true, false, true},
+ {"dn", true, false, true}
+ }
+};
+
+static int componentorder[4] = {0, 1, 2, 3};
+
+rtexture_t *R_LoadCubemap(const char *basename)
+{
+ int i, j, cubemapsize;
+ unsigned char *cubemappixels, *image_buffer;
+ rtexture_t *cubemaptexture;
+ char name[256];
+ // must start 0 so the first loadimagepixels has no requested width/height
+ cubemapsize = 0;
+ cubemappixels = NULL;
+ cubemaptexture = NULL;
+ // keep trying different suffix groups (posx, px, rt) until one loads
+ for (j = 0;j < 3 && !cubemappixels;j++)
+ {
+ // load the 6 images in the suffix group
+ for (i = 0;i < 6;i++)
+ {
+ // generate an image name based on the base and and suffix
+ dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+ // load it
+ if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
+ {
+ // an image loaded, make sure width and height are equal
+ if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
+ {
+ // if this is the first image to load successfully, allocate the cubemap memory
+ if (!cubemappixels && image_width >= 1)
+ {
+ cubemapsize = image_width;
+ // note this clears to black, so unavailable sides are black
+ cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
+ }
+ // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
+ if (cubemappixels)
+ Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
+ }
+ else
+ Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
+ // free the image
+ Mem_Free(image_buffer);
+ }
+ }
+ }
+ // if a cubemap loaded, upload it
+ if (cubemappixels)
+ {
+ if (developer_loading.integer)
+ Con_Printf("loading cubemap \"%s\"\n", basename);
+
+ cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
+ Mem_Free(cubemappixels);
+ }
+ else
+ {
+ Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
+ if (developer_loading.integer)
+ {
+ Con_Printf("(tried tried images ");
+ for (j = 0;j < 3;j++)
+ for (i = 0;i < 6;i++)
+ Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
+ Con_Print(" and was unable to find any of them).\n");
+ }
+ }
+ return cubemaptexture;
+}
+
+rtexture_t *R_GetCubemap(const char *basename)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
+ return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
+ if (i >= MAX_CUBEMAPS)
+ return r_texture_whitecube;
+ r_texture_numcubemaps++;
+ strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
+ r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
+ return r_texture_cubemaps[i].texture;
+}
+
+void R_FreeCubemaps(void)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ {
+ if (developer_loading.integer)
+ Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
+ if (r_texture_cubemaps[i].texture)
+ R_FreeTexture(r_texture_cubemaps[i].texture);
+ }
+ r_texture_numcubemaps = 0;
+}
+
void R_Main_FreeViewCache(void)
{
if (r_refdef.viewcache.entityvisible)
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_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
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));
memset(&r_waterstate, 0, sizeof(r_waterstate));
+ r_glsl_permutation = NULL;
memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
+ glslshaderstring = NULL;
#ifdef SUPPORTCG
+ r_cg_permutation = NULL;
memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
+ cgshaderstring = NULL;
#endif
memset(&r_svbsp, 0, sizeof (r_svbsp));
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;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
+ r_glsl_permutation = NULL;
+ memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
+ glslshaderstring = NULL;
+#ifdef SUPPORTCG
+ r_cg_permutation = NULL;
+ memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
+ cgshaderstring = NULL;
+#endif
R_GLSL_Restart_f();
}
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);
Cvar_RegisterVariable(&r_shadows_castfrombmodels);
Cvar_RegisterVariable(&r_shadows_throwdistance);
Cvar_RegisterVariable(&r_shadows_throwdirection);
+ Cvar_RegisterVariable(&r_shadows_focus);
+ Cvar_RegisterVariable(&r_shadows_shadowmapscale);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
Cvar_RegisterVariable(&r_transparentdepthmasking);
Cvar_RegisterVariable(&r_texture_dds_load);
Cvar_RegisterVariable(&r_texture_dds_save);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&gl_combine);
Cvar_RegisterVariable(&r_glsl);
for (i = 0;i < r_refdef.scene.numentities;i++)
if (r_refdef.viewcache.entityvisible[i])
R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
-
- if (r_shadows.integer)
- for (i = 0;i < r_refdef.scene.numentities;i++)
- if (!r_refdef.viewcache.entityvisible[i])
- R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
}
//==================================================================================
entity_render_t *ent;
vec3_t tempdiffusenormal, avg;
vec_t f, fa, fd, fdd;
+ qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
// skip unseen models
- if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
+ if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
continue;
// skip bsp models
boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
+ // return true if eye is inside enlarged box
+ if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
+ return true;
+
// try center
VectorCopy(eye, start);
VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
int samples;
entity_render_t *ent;
- renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
+ renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
+ : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
+ : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
+ : 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))
{
// (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
+ 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_RenderScene();
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;
}
}
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);
if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
if (r_cg_permutation->fp_ViewTintColor ) cgGLSetParameter4f( r_cg_permutation->fp_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
- if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
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();
static void R_DrawLocs(void);
static void R_DrawEntityBBoxes(void);
static void R_DrawModelDecals(void);
+extern void R_DrawModelShadows(void);
+extern void R_DrawModelShadowMaps(void);
extern cvar_t cl_decals_newsystem;
extern qboolean r_shadow_usingdeferredprepass;
void R_RenderScene(void)
{
+ qboolean shadowmapping = false;
+
+ if (r_timereport_active)
+ R_TimeReport("beginscene");
+
r_refdef.stats.renders++;
R_UpdateFogColor();
Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+ if (r_timereport_active)
+ R_TimeReport("skystartframe");
+
if (cl.csqc_vidvars.drawworld)
{
// don't let sound skip if going slow
R_TimeReport("animation");
R_Shadow_PrepareLights();
+ if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
+ R_Shadow_PrepareModelShadows();
if (r_timereport_active)
R_TimeReport("preparelights");
+ if (R_Shadow_ShadowMappingEnabled())
+ shadowmapping = true;
+
if (r_shadow_usingdeferredprepass)
R_Shadow_DrawPrepass();
R_TimeReport("modeldepth");
}
+ if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
+ {
+ R_DrawModelShadowMaps();
+ R_ResetViewRendering3D();
+ // don't let sound skip if going slow
+ if (r_refdef.scene.extraupdate)
+ S_ExtraUpdate ();
+ }
+
if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
{
r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !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 && 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();
f = FS_LoadFile(name, tempmempool, true, &filesize);
if (f)
{
- if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
+ if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
Mem_Free(f);
}
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;
t->glosstexture = r_texture_black;
t->glowtexture = t->currentskinframe->glow;
t->fogtexture = t->currentskinframe->fog;
+ t->reflectmasktexture = t->currentskinframe->reflect;
if (t->backgroundnumskinframes)
{
t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
t->glosstexture = r_texture_black;
t->glowtexture = NULL;
t->fogtexture = NULL;
+ t->reflectmasktexture = NULL;
t->backgroundbasetexture = NULL;
t->backgroundnmaptexture = r_texture_blanknormalmap;
t->backgroundglosstexture = r_texture_black;
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 | MATERIALFLAG_CAMERA)))
+ return;
RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
if (prepass)
{
// render screenspace normalmap to texture
GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
+ 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);
R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
GL_DepthMask(false);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
+ else
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
else
{
// render surface normally
GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass)
+ if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
{
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
return;
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass)
+ if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
{
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
return;
int texturenumsurfaces, endsurface;
texture_t *texture;
const msurface_t *surface;
- const msurface_t *texturesurfacelist[256];
+#define MAXBATCH_TRANSPARENTSURFACES 256
+ const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
// if the model is static it doesn't matter what value we give for
// wantnormals and wanttangents, so this logic uses only rules applicable
rsurface.texture = R_GetCurrentTexture(texture);
rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
// scan ahead until we find a different texture
- endsurface = min(i + 1024, numsurfaces);
+ endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
texturenumsurfaces = 0;
texturesurfacelist[texturenumsurfaces++] = surface;
for (;j < endsurface;j++)
tridecal_t *decal;
tridecal_t *decals;
int i;
- int maxdecals;
// expand or initialize the system
if (decalsystem->maxdecals <= decalsystem->numdecals)
}
// grab a decal and search for another free slot for the next one
- maxdecals = decalsystem->maxdecals;
decals = decalsystem->decals;
decal = decalsystem->decals + (i = decalsystem->freedecal++);
for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
const msurface_t *surfaces;
const int *surfacelist;
const texture_t *texture;
- int numvertices;
int numtriangles;
int numsurfacelist;
int surfacelistindex;
int surfaceindex;
int triangleindex;
- int decalsurfaceindex;
int cornerindex;
int index;
int numpoints;
float localmins[3];
float localmaxs[3];
float localsize;
- float ilocalsize;
float v[9][3];
float tc[9][2];
float c[9][4];
Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
VectorNormalize(localnormal);
localsize = worldsize*rsurface.inversematrixscale;
- ilocalsize = 1.0f / localsize;
localmins[0] = localorigin[0] - localsize;
localmins[1] = localorigin[1] - localsize;
localmins[2] = localorigin[2] - localsize;
{
surfaceindex = surfacelist[surfacelistindex];
surface = surfaces + surfaceindex;
+ // check cull box first because it rejects more than any other check
+ if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
+ continue;
// skip transparent surfaces
texture = surface->texture;
if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
continue;
if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
continue;
- if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
- continue;
- decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
- numvertices = surface->num_vertices;
numtriangles = surface->num_triangles;
for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
{
decalsystem_t *decalsystem = &ent->decalsystem;
int numdecals;
tridecal_t *decal;
- float fadedelay;
float faderate;
float alpha;
float *v3f;
decalsystem->lastupdatetime = cl.time;
decal = decalsystem->decals;
- fadedelay = cl_decals_time.value;
faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
// update vertex positions for animated models
VectorCopy(decal->vertex3f[2], v3f + 6);
}
+ if (r_refdef.fogenabled)
+ {
+ alpha = RSurf_FogVertex(v3f);
+ VectorScale(c4f, alpha, c4f);
+ alpha = RSurf_FogVertex(v3f + 3);
+ VectorScale(c4f + 4, alpha, c4f + 4);
+ alpha = RSurf_FogVertex(v3f + 6);
+ VectorScale(c4f + 8, alpha, c4f + 8);
+ }
+
v3f += 9;
c4f += 12;
t2f += 6;
{
r_refdef.stats.drawndecals += numtris;
- if (r_refdef.fogenabled)
- {
- switch(vid.renderpath)
- {
- case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
- case RENDERPATH_GL13:
- case RENDERPATH_GL11:
- for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
- {
- alpha = RSurf_FogVertex(v3f);
- c4f[0] *= alpha;
- c4f[1] *= alpha;
- c4f[2] *= alpha;
- }
- break;
- }
- }
-
// now render the decals all at once
// (this assumes they all use one particle font texture!)
RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
}
}
+extern cvar_t mod_collision_bih;
void R_DrawDebugModel(void)
{
entity_render_t *ent = rsurface.entity;
int i, j, k, l, flagsmask;
- const int *elements;
- q3mbrush_t *brush;
const msurface_t *surface;
dp_model_t *model = ent->model;
vec3_t v;
GL_DepthMask(false);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
+ if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
{
+ int triangleindex;
+ int bihleafindex;
+ qboolean cullbox = ent == r_refdef.scene.worldentity;
+ const q3mbrush_t *brush;
+ const bih_t *bih = &model->collision_bih;
+ const bih_leaf_t *bihleaf;
+ float vertex3f[3][3];
GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
- for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
- {
- if (brush->colbrushf && brush->colbrushf->numtriangles)
- {
- R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
- GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
- }
- }
- for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+ cullbox = false;
+ for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
{
- if (surface->num_collisiontriangles)
+ if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
+ continue;
+ switch (bihleaf->type)
{
- R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
- GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
+ case BIH_BRUSH:
+ brush = model->brush.data_brushes + bihleaf->itemindex;
+ if (brush->colbrushf && brush->colbrushf->numtriangles)
+ {
+ R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
+ }
+ break;
+ case BIH_COLLISIONTRIANGLE:
+ triangleindex = bihleaf->itemindex;
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
+ R_Mesh_VertexPointer(vertex3f[0], 0, 0);
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ break;
+ case BIH_RENDERTRIANGLE:
+ triangleindex = bihleaf->itemindex;
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
+ R_Mesh_VertexPointer(vertex3f[0], 0, 0);
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ break;
}
}
}
GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
else
GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
- elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
const msurface_t **r_surfacelist = NULL;
void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
{
- int i, j, endj, f, flagsmask;
- texture_t *t;
+ int i, j, endj, flagsmask;
dp_model_t *model = r_refdef.scene.worldmodel;
msurface_t *surfaces;
unsigned char *update;
return;
}
- f = 0;
- t = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
{
- int i, j, endj, f, flagsmask;
- texture_t *t;
+ int i, j, endj, flagsmask;
dp_model_t *model = ent->model;
msurface_t *surfaces;
unsigned char *update;
else if (prepass)
RSurf_ActiveModelEntity(ent, true, true, true);
else if (depthonly)
- RSurf_ActiveModelEntity(ent, false, false, false);
+ {
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
+ break;
+ }
+ }
else
{
switch (vid.renderpath)
return;
}
- f = 0;
- t = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
texture.currentskinframe = skinframe;
texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
+ texture.offsetmapping = OFFSETMAPPING_OFF;
+ texture.offsetscale = 1;
texture.specularscalemod = 1;
texture.specularpowermod = 1;