#include "r_shadow.h"
#include "polygon.h"
#include "image.h"
+#include "ft2.h"
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
-static int r_frame = 0; ///< used only by R_GetCurrentTexture
+static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
-qboolean r_loadnormalmap;
-qboolean r_loadgloss;
+static qboolean r_loadnormalmap;
+static qboolean r_loadgloss;
qboolean r_loadfog;
+static qboolean r_loaddds;
+static qboolean r_savedds;
//
// screen size info
cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
+cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
+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"};
cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
-cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
+cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
+cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
+cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
+
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
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;
data[1] = 128; // normal Y
data[0] = 255; // normal Z
data[3] = 128; // height
- r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
+ r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
data[0] = 255;
data[1] = 255;
data[2] = 255;
data[3] = 255;
- r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
+ r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
data[0] = 128;
data[1] = 128;
data[2] = 128;
data[3] = 255;
- r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
+ r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 255;
- r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
+ r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
}
static void R_BuildNoTexture(void)
}
}
}
- r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
+ r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
}
static void R_BuildWhiteCube(void)
{
unsigned char data[6*1*1*4];
memset(data, 255, sizeof(data));
- r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
}
static void R_BuildNormalizationCube(void)
vec3_t v;
vec_t s, t, intensity;
#define NORMSIZE 64
- unsigned char data[6][NORMSIZE][NORMSIZE][4];
+ unsigned char *data;
+ data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
for (side = 0;side < 6;side++)
{
for (y = 0;y < NORMSIZE;y++)
break;
}
intensity = 127.0f / sqrt(DotProduct(v, v));
- data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
- data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
- data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
- data[side][y][x][3] = 255;
+ data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
+ data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
+ data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
+ data[((side*64+y)*64+x)*4+3] = 255;
}
}
}
- r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ Mem_Free(data);
}
static void R_BuildFogTexture(void)
for (x = 0;x < FOGMASKTABLEWIDTH;x++)
{
d = (x * r - r_refdef.fogmasktable_start);
- if(developer.integer >= 100)
- Con_Printf("%f ", d);
+ if(developer_extra.integer)
+ Con_DPrintf("%f ", d);
d = max(0, d);
if (r_fog_exp2.integer)
alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
else
alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
- if(developer.integer >= 100)
- Con_Printf(" : %f ", alpha);
+ if(developer_extra.integer)
+ Con_DPrintf(" : %f ", alpha);
alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
- if(developer.integer >= 100)
- Con_Printf(" = %f\n", alpha);
+ if(developer_extra.integer)
+ Con_DPrintf(" = %f\n", alpha);
r_refdef.fogmasktable[x] = bound(0, alpha, 1);
}
}
else
{
- r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
- //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
+ r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
+ //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
}
}
+//=======================================================================================================================================================
+
static const char *builtinshaderstring =
"// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
"// written by Forest 'LordHavoc' Hale\n"
+"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"// enable various extensions depending on permutation:\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\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) || defined(USEREFLECTCUBE)\n"
+"#define USEEYEVECTOR\n"
+"#endif\n"
"\n"
-"#ifdef USESHADOWMAPRECT\n"
+"#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
"# extension GL_ARB_texture_rectangle : enable\n"
"#endif\n"
"\n"
"# extension GL_EXT_gpu_shader4 : enable\n"
"#endif\n"
"\n"
-"#ifdef USESHADOWSAMPLER\n"
-"# extension GL_ARB_shadow : enable\n"
-"#endif\n"
-"\n"
-"// common definitions between vertex shader and fragment shader:\n"
+"//#ifdef USESHADOWSAMPLER\n"
+"//# extension GL_ARB_shadow : enable\n"
+"//#endif\n"
"\n"
"//#ifdef __GLSL_CG_DATA_TYPES\n"
"//# define myhalf half\n"
"//# define myhalf2 half2\n"
-"//# define myhalf3half3\n"
+"//# define myhalf3 half3\n"
"//# define myhalf4 half4\n"
"//#else\n"
"# define myhalf float\n"
"# define myhalf4 vec4\n"
"//#endif\n"
"\n"
-"#ifdef USEFOGINSIDE\n"
-"# define USEFOG\n"
-"#else\n"
-"# ifdef USEFOGOUTSIDE\n"
-"# define USEFOG\n"
-"# endif\n"
+"#ifdef VERTEX_SHADER\n"
+"uniform mat4 ModelViewProjectionMatrix;\n"
"#endif\n"
"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
-"\n"
-"# ifdef VERTEX_SHADER\n"
+"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
-" gl_Position = ftransform();\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n"
-"# endif\n"
+"#endif\n"
+"#else // !MODE_DEPTH_ORSHADOW\n"
+"\n"
+"\n"
+"\n"
"\n"
-"#else\n"
"#ifdef MODE_SHOWDEPTH\n"
-"# ifdef VERTEX_SHADER\n"
+"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
-" gl_Position = ftransform();\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
"}\n"
-"# endif\n"
-"# ifdef FRAGMENT_SHADER\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
"void main(void)\n"
"{\n"
" gl_FragColor = gl_Color;\n"
"}\n"
-"# endif\n"
-"\n"
+"#endif\n"
"#else // !MODE_SHOWDEPTH\n"
"\n"
+"\n"
+"\n"
+"\n"
"#ifdef MODE_POSTPROCESS\n"
-"# ifdef VERTEX_SHADER\n"
+"varying vec2 TexCoord1;\n"
+"varying vec2 TexCoord2;\n"
+"\n"
+"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
-" gl_FrontColor = gl_Color;\n"
-" gl_Position = ftransform();\n"
-" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
+" TexCoord1 = gl_MultiTexCoord0.xy;\n"
"#ifdef USEBLOOM\n"
-" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
+" TexCoord2 = gl_MultiTexCoord1.xy;\n"
"#endif\n"
"}\n"
-"# endif\n"
-"# ifdef FRAGMENT_SHADER\n"
+"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D Texture_First;\n"
"#ifdef USEBLOOM\n"
"uniform sampler2D Texture_Second;\n"
"uniform float Saturation;\n"
"#endif\n"
"#ifdef USEVIEWTINT\n"
-"uniform vec4 TintColor;\n"
+"uniform vec4 ViewTintColor;\n"
"#endif\n"
"//uncomment these if you want to use them:\n"
"uniform vec4 UserVec1;\n"
"uniform vec2 PixelSize;\n"
"void main(void)\n"
"{\n"
-" gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
+" gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
"#ifdef USEBLOOM\n"
-" gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
+" gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
"#endif\n"
"#ifdef USEVIEWTINT\n"
-" gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
+" gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
"#endif\n"
"\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"
-" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
-" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
-" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
-" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
-" gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\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"
"#endif\n"
"\n"
"#ifdef USESATURATION\n"
" //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
-" myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
+" float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
"#endif\n"
" gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
"#endif\n"
"}\n"
-"# endif\n"
+"#endif\n"
+"#else // !MODE_POSTPROCESS\n"
+"\n"
+"\n"
"\n"
"\n"
-"#else\n"
"#ifdef MODE_GENERIC\n"
-"# ifdef VERTEX_SHADER\n"
+"#ifdef USEDIFFUSE\n"
+"varying vec2 TexCoord1;\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
+"varying vec2 TexCoord2;\n"
+"#endif\n"
+"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
" gl_FrontColor = gl_Color;\n"
-"# ifdef USEDIFFUSE\n"
-" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
-"# endif\n"
-"# ifdef USESPECULAR\n"
-" gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
-"# endif\n"
-" gl_Position = ftransform();\n"
+"#ifdef USEDIFFUSE\n"
+" TexCoord1 = gl_MultiTexCoord0.xy;\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
+" TexCoord2 = gl_MultiTexCoord1.xy;\n"
+"#endif\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n"
-"# endif\n"
-"# ifdef FRAGMENT_SHADER\n"
+"#endif\n"
"\n"
-"# ifdef USEDIFFUSE\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#ifdef USEDIFFUSE\n"
"uniform sampler2D Texture_First;\n"
-"# endif\n"
-"# ifdef USESPECULAR\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
"uniform sampler2D Texture_Second;\n"
-"# endif\n"
+"#endif\n"
"\n"
"void main(void)\n"
"{\n"
" gl_FragColor = gl_Color;\n"
-"# ifdef USEDIFFUSE\n"
-" gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
-"# endif\n"
+"#ifdef USEDIFFUSE\n"
+" gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
+"#endif\n"
"\n"
-"# ifdef USESPECULAR\n"
-" vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
-"# endif\n"
-"# ifdef USECOLORMAPPING\n"
+"#ifdef USESPECULAR\n"
+" vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
+"# ifdef USECOLORMAPPING\n"
" gl_FragColor *= tex2;\n"
-"# endif\n"
-"# ifdef USEGLOW\n"
+"# endif\n"
+"# ifdef USEGLOW\n"
" gl_FragColor += tex2;\n"
-"# endif\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
+"# endif\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
" gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
-"# endif\n"
-"}\n"
"# endif\n"
-"\n"
+"#endif\n"
+"}\n"
+"#endif\n"
"#else // !MODE_GENERIC\n"
+"\n"
+"\n"
+"\n"
+"\n"
"#ifdef MODE_BLOOMBLUR\n"
-"# ifdef VERTEX_SHADER\n"
+"varying TexCoord;\n"
+"#ifdef VERTEX_SHADER\n"
"void main(void)\n"
"{\n"
" gl_FrontColor = gl_Color;\n"
-" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
-" gl_Position = ftransform();\n"
+" TexCoord = gl_MultiTexCoord0.xy;\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n"
-"# endif\n"
-"# ifdef FRAGMENT_SHADER\n"
+"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D Texture_First;\n"
"uniform vec4 BloomBlur_Parameters;\n"
"\n"
"void main(void)\n"
"{\n"
" int i;\n"
-" vec2 tc = gl_TexCoord[0].xy;\n"
+" vec2 tc = TexCoord;\n"
" vec3 color = texture2D(Texture_First, tc).rgb;\n"
" tc += BloomBlur_Parameters.xy;\n"
" for (i = 1;i < SAMPLES;i++)\n"
" }\n"
" gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
"}\n"
-"# endif\n"
-"\n"
+"#endif\n"
"#else // !MODE_BLOOMBLUR\n"
+"#ifdef MODE_REFRACTION\n"
+"varying vec2 TexCoord;\n"
+"varying vec4 ModelViewProjectionPosition;\n"
+"uniform mat4 TexMatrix;\n"
+"#ifdef VERTEX_SHADER\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"uniform sampler2D Texture_Normal;\n"
+"uniform sampler2D Texture_Refraction;\n"
+"uniform sampler2D Texture_Reflection;\n"
+"\n"
+"uniform vec4 DistortScaleRefractReflect;\n"
+"uniform vec4 ScreenScaleRefractReflect;\n"
+"uniform vec4 ScreenCenterRefractReflect;\n"
+"uniform vec4 RefractColor;\n"
+"uniform vec4 ReflectColor;\n"
+"uniform float ReflectFactor;\n"
+"uniform float ReflectOffset;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
+" //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+" vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+" vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_REFRACTION\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_WATER\n"
+"varying vec2 TexCoord;\n"
+"varying vec3 EyeVector;\n"
+"varying vec4 ModelViewProjectionPosition;\n"
+"#ifdef VERTEX_SHADER\n"
+"uniform vec3 EyePosition;\n"
+"uniform mat4 TexMatrix;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
+" vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"uniform sampler2D Texture_Normal;\n"
+"uniform sampler2D Texture_Refraction;\n"
+"uniform sampler2D Texture_Reflection;\n"
+"\n"
+"uniform vec4 DistortScaleRefractReflect;\n"
+"uniform vec4 ScreenScaleRefractReflect;\n"
+"uniform vec4 ScreenCenterRefractReflect;\n"
+"uniform vec4 RefractColor;\n"
+"uniform vec4 ReflectColor;\n"
+"uniform float ReflectFactor;\n"
+"uniform float ReflectOffset;\n"
+"\n"
+"void main(void)\n"
+"{\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"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
+" f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
+" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
+" gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_WATER\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"// common definitions between vertex shader and fragment shader:\n"
"\n"
"varying vec2 TexCoord;\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"varying vec2 TexCoord2;\n"
"#endif\n"
+"#ifdef USELIGHTMAP\n"
"varying vec2 TexCoordLightmap;\n"
+"#endif\n"
"\n"
"#ifdef MODE_LIGHTSOURCE\n"
"varying vec3 CubeVector;\n"
"#endif\n"
"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"varying vec3 LightVector;\n"
-"#endif\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
+"#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
"varying vec3 LightVector;\n"
"#endif\n"
"\n"
+"#ifdef USEEYEVECTOR\n"
"varying vec3 EyeVector;\n"
+"#endif\n"
"#ifdef USEFOG\n"
-"varying vec3 EyeVectorModelSpace;\n"
-"varying float FogPlaneVertexDist;\n"
+"varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
"#endif\n"
"\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"
-"\n"
-"#ifdef MODE_WATER\n"
-"varying vec4 ModelViewProjectionPosition;\n"
-"#endif\n"
-"#ifdef MODE_REFRACTION\n"
-"varying vec4 ModelViewProjectionPosition;\n"
"#endif\n"
+"\n"
"#ifdef USEREFLECTION\n"
"varying vec4 ModelViewProjectionPosition;\n"
"#endif\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform vec3 LightPosition;\n"
+"varying vec4 ModelViewPosition;\n"
+"#endif\n"
"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// vertex shader specific:\n"
-"#ifdef VERTEX_SHADER\n"
-"\n"
+"#ifdef MODE_LIGHTSOURCE\n"
"uniform vec3 LightPosition;\n"
+"#endif\n"
"uniform vec3 EyePosition;\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
"uniform vec3 LightDir;\n"
+"#endif\n"
"uniform vec4 FogPlane;\n"
"\n"
-"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
"\n"
-"void main(void)\n"
-"{\n"
-" gl_FrontColor = gl_Color;\n"
-" // copy the surface texcoord\n"
-" TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
-"#ifdef USEVERTEXTEXTUREBLEND\n"
-" TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
-"#endif\n"
-"#ifndef MODE_LIGHTSOURCE\n"
-"# ifndef MODE_LIGHTDIRECTION\n"
-" TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
-"# endif\n"
-"#endif\n"
"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" // transform vertex position into light attenuation/cubemap space\n"
-" // (-1 to +1 across the light box)\n"
-" CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
"\n"
-" // transform unnormalized light direction into tangent space\n"
-" // (we use unnormalized to ensure that it interpolates correctly and then\n"
-" // normalize it per pixel)\n"
-" vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
-" LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
-" LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
-" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
"\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-" LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
-" LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
-" LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
-"#endif\n"
+"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
"\n"
-" // transform unnormalized eye direction into tangent space\n"
-"#ifndef USEFOG\n"
-" vec3 EyeVectorModelSpace;\n"
-"#endif\n"
-" EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
-" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
-" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
-" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+"// fragment shader specific:\n"
+"#ifdef FRAGMENT_SHADER\n"
"\n"
-"#ifdef USEFOG\n"
-" FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-" VectorS = gl_MultiTexCoord1.xyz;\n"
-" VectorT = gl_MultiTexCoord2.xyz;\n"
-" VectorR = gl_MultiTexCoord3.xyz;\n"
-"#endif\n"
-"\n"
-"//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
-"// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
-"// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
-"// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
-"//#endif\n"
-"\n"
-"// transform vertex to camera space, using ftransform to match non-VS\n"
-" // rendering\n"
-" gl_Position = ftransform();\n"
-"\n"
-"#ifdef MODE_WATER\n"
-" ModelViewProjectionPosition = gl_Position;\n"
-"#endif\n"
-"#ifdef MODE_REFRACTION\n"
-" ModelViewProjectionPosition = gl_Position;\n"
-"#endif\n"
-"#ifdef USEREFLECTION\n"
-" ModelViewProjectionPosition = gl_Position;\n"
-"#endif\n"
-"}\n"
-"\n"
-"#endif // VERTEX_SHADER\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"// fragment shader specific:\n"
-"#ifdef FRAGMENT_SHADER\n"
-"\n"
-"// 13 textures, we can only use up to 16 on DX9-class hardware\n"
"uniform sampler2D Texture_Normal;\n"
"uniform sampler2D Texture_Color;\n"
"uniform sampler2D Texture_Gloss;\n"
+"#ifdef USEGLOW\n"
"uniform sampler2D Texture_Glow;\n"
+"#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
"uniform sampler2D Texture_SecondaryNormal;\n"
"uniform sampler2D Texture_SecondaryColor;\n"
"uniform sampler2D Texture_SecondaryGloss;\n"
+"#ifdef USEGLOW\n"
"uniform sampler2D Texture_SecondaryGlow;\n"
+"#endif\n"
+"#endif\n"
+"#ifdef USECOLORMAPPING\n"
"uniform sampler2D Texture_Pants;\n"
"uniform sampler2D Texture_Shirt;\n"
+"#endif\n"
+"#ifdef USEFOG\n"
"uniform sampler2D Texture_FogMask;\n"
+"#endif\n"
+"#ifdef USELIGHTMAP\n"
"uniform sampler2D Texture_Lightmap;\n"
+"#endif\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"uniform sampler2D Texture_Deluxemap;\n"
-"uniform sampler2D Texture_Refraction;\n"
-"uniform sampler2D Texture_Reflection;\n"
-"uniform sampler2D Texture_Attenuation;\n"
-"uniform samplerCube Texture_Cube;\n"
-"\n"
-"#define showshadowmap 0\n"
-"\n"
-"#ifdef USESHADOWMAPRECT\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
-"# else\n"
-"uniform sampler2DRect Texture_ShadowMapRect;\n"
-"# endif\n"
"#endif\n"
-"\n"
-"#ifdef USESHADOWMAP2D\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform sampler2DShadow Texture_ShadowMap2D;\n"
-"# else\n"
-"uniform sampler2D Texture_ShadowMap2D;\n"
-"# endif\n"
+"#ifdef USEREFLECTION\n"
+"uniform sampler2D Texture_Reflection;\n"
"#endif\n"
"\n"
-"#ifdef USESHADOWMAPVSDCT\n"
-"uniform samplerCube Texture_CubeProjection;\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform sampler2D Texture_ScreenDepth;\n"
+"uniform sampler2D Texture_ScreenNormalMap;\n"
"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPCUBE\n"
-"# ifdef USESHADOWSAMPLER\n"
-"uniform samplerCubeShadow Texture_ShadowMapCube;\n"
-"# else\n"
-"uniform samplerCube Texture_ShadowMapCube;\n"
-"# endif\n"
+"#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform sampler2D Texture_ScreenDiffuse;\n"
+"uniform sampler2D Texture_ScreenSpecular;\n"
"#endif\n"
"\n"
-"uniform myhalf3 LightColor;\n"
-"uniform myhalf3 AmbientColor;\n"
-"uniform myhalf3 DiffuseColor;\n"
-"uniform myhalf3 SpecularColor;\n"
"uniform myhalf3 Color_Pants;\n"
"uniform myhalf3 Color_Shirt;\n"
"uniform myhalf3 FogColor;\n"
"\n"
-"uniform myhalf4 TintColor;\n"
-"\n"
-"\n"
-"//#ifdef MODE_WATER\n"
-"uniform vec4 DistortScaleRefractReflect;\n"
-"uniform vec4 ScreenScaleRefractReflect;\n"
-"uniform vec4 ScreenCenterRefractReflect;\n"
-"uniform myhalf4 RefractColor;\n"
-"uniform myhalf4 ReflectColor;\n"
-"uniform myhalf ReflectFactor;\n"
-"uniform myhalf ReflectOffset;\n"
-"//#else\n"
-"//# ifdef MODE_REFRACTION\n"
-"//uniform vec4 DistortScaleRefractReflect;\n"
-"//uniform vec4 ScreenScaleRefractReflect;\n"
-"//uniform vec4 ScreenCenterRefractReflect;\n"
-"//uniform myhalf4 RefractColor;\n"
-"//# ifdef USEREFLECTION\n"
-"//uniform myhalf4 ReflectColor;\n"
-"//# endif\n"
-"//# else\n"
-"//# ifdef USEREFLECTION\n"
-"//uniform vec4 DistortScaleRefractReflect;\n"
-"//uniform vec4 ScreenScaleRefractReflect;\n"
-"//uniform vec4 ScreenCenterRefractReflect;\n"
-"//uniform myhalf4 ReflectColor;\n"
-"//# endif\n"
-"//# endif\n"
-"//#endif\n"
-"\n"
-"uniform myhalf3 GlowColor;\n"
-"uniform myhalf SceneBrightness;\n"
-"\n"
-"uniform float OffsetMapping_Scale;\n"
-"uniform float OffsetMapping_Bias;\n"
+"#ifdef USEFOG\n"
"uniform float FogRangeRecip;\n"
"uniform float FogPlaneViewDist;\n"
"uniform float FogHeightFade;\n"
-"\n"
-"uniform myhalf AmbientScale;\n"
-"uniform myhalf DiffuseScale;\n"
-"uniform myhalf SpecularScale;\n"
-"uniform myhalf SpecularPower;\n"
+"float FogVertex(void)\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"
+"#else\n"
+" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"#endif\n"
+" return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
+"}\n"
+"#endif\n"
"\n"
"#ifdef USEOFFSETMAPPING\n"
+"uniform float OffsetMapping_Scale;\n"
"vec2 OffsetMapping(vec2 TexCoord)\n"
"{\n"
"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
"}\n"
"#endif // USEOFFSETMAPPING\n"
"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"uniform sampler2D Texture_Attenuation;\n"
+"uniform samplerCube Texture_Cube;\n"
+"\n"
+"#ifdef USESHADOWMAPRECT\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
+"# else\n"
+"uniform sampler2DRect Texture_ShadowMapRect;\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAP2D\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform sampler2DShadow Texture_ShadowMap2D;\n"
+"# else\n"
+"uniform sampler2D Texture_ShadowMap2D;\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"uniform samplerCube Texture_CubeProjection;\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPCUBE\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform samplerCubeShadow Texture_ShadowMapCube;\n"
+"# else\n"
+"uniform samplerCube Texture_ShadowMapCube;\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
"uniform vec2 ShadowMap_TextureScale;\n"
"uniform vec4 ShadowMap_Parameters;\n"
"#endif\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
+"# ifndef USESHADOWMAPVSDCT\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-"# ifndef USESHADOWMAPVSDCT\n"
" vec2 tc;\n"
" vec2 offset;\n"
" float ma;\n"
" vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
" stc.xy += offset * ShadowMap_Parameters.y;\n"
" stc.z += ShadowMap_Parameters.z;\n"
-"# if showshadowmap\n"
-" stc.xy *= ShadowMap_TextureScale;\n"
-"# endif\n"
" return stc;\n"
+"}\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"
-"# if showshadowmap\n"
-" stc.xy *= ShadowMap_TextureScale;\n"
-"# endif\n"
" return stc;\n"
-"# endif\n"
"}\n"
+"# endif\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"#ifdef USESHADOWMAPCUBE\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"
+" vec3 adir = abs(dir);\n"
+" return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
-"#if !showshadowmap\n"
"# ifdef USESHADOWMAPRECT\n"
"float ShadowMapCompare(vec3 dir)\n"
"{\n"
"\n"
"# ifdef USESHADOWMAPPCF\n"
"# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
-" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
"# else\n"
-" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
+" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
"# endif\n"
"\n"
"# else\n"
"# ifdef USESHADOWMAPPCF\n"
"# if USESHADOWMAPPCF > 1\n"
"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
-" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
-" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
-" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
-" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
-" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
-" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
+" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
+" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
+" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
+" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
"# else\n"
"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
-" vec2 offset = fract(shadowmaptc.xy);\n"
-" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
-" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
-" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
-" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
-" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+" vec2 offset = fract(shadowmaptc.xy);\n"
+" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
+" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
+" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
+" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
+" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
"# endif\n"
"# else\n"
-" f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+" f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
"# endif\n"
"\n"
"# endif\n"
"# ifdef USESHADOWMAP2D\n"
"float ShadowMapCompare(vec3 dir)\n"
"{\n"
-" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
-" float f;\n"
+" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
+" float f;\n"
"\n"
"# ifdef USESHADOWSAMPLER\n"
"# ifdef USESHADOWMAPPCF\n"
"# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
-" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
-" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
+" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
"# else\n"
-" f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
+" f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
"# endif\n"
"# else\n"
"# ifdef USESHADOWMAPPCF\n"
"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
"# ifdef GL_ARB_texture_gather\n"
-"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
+"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
"# else\n"
-"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
+"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
"# endif\n"
-" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
-" center *= ShadowMap_TextureScale;\n"
-" vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
-" vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
-" vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
-" vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
-" vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
-" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
+" vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
+" vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
+" vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
+" vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
+" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
"# else\n"
"# ifdef GL_EXT_gpu_shader4\n"
"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
"# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
"# endif\n"
"# if USESHADOWMAPPCF > 1\n"
-" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
-" center *= ShadowMap_TextureScale;\n"
-" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
-" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
-" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
-" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
-" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
+" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
+" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
+" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
+" vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
"# else\n"
-" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
-" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
-" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
-" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
-" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
-" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
+" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
+" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
+" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
+" vec3 cols = row2 + mix(row1, row3, offset.y);\n"
+" f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
"# endif\n"
"# endif\n"
"# else\n"
-" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
+" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
"# endif\n"
"# endif\n"
-" return f;\n"
+" return f;\n"
"}\n"
"# endif\n"
"\n"
"# ifdef USESHADOWMAPCUBE\n"
"float ShadowMapCompare(vec3 dir)\n"
"{\n"
-" // apply depth texture cubemap as light filter\n"
-" vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
-" float f;\n"
+" // apply depth texture cubemap as light filter\n"
+" vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
+" float f;\n"
"# ifdef USESHADOWSAMPLER\n"
-" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
+" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
"# else\n"
-" f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
+" f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
"# endif\n"
-" return f;\n"
+" return f;\n"
"}\n"
"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef MODE_WATER\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // FRAGMENT_SHADER\n"
"\n"
-"// water pass\n"
-"void main(void)\n"
-"{\n"
-"#ifdef USEOFFSETMAPPING\n"
-" // apply offsetmapping\n"
-" vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
-"#define TexCoord TexCoordOffset\n"
-"#endif\n"
"\n"
-" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
-" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-" vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
-" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-" // FIXME temporary hack to detect the case that the reflection\n"
-" // gets blackened at edges due to leaving the area that contains actual\n"
-" // content.\n"
-" // Remove this 'ack once we have a better way to stop this thing from\n"
-" // 'appening.\n"
-" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
-" f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-" ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
-" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
-" gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
-"}\n"
"\n"
-"#else // !MODE_WATER\n"
-"#ifdef MODE_REFRACTION\n"
"\n"
-"// refraction pass\n"
+"#ifdef MODE_DEFERREDGEOMETRY\n"
+"#ifdef VERTEX_SHADER\n"
+"uniform mat4 TexMatrix;\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"uniform mat4 BackgroundTexMatrix;\n"
+"#endif\n"
+"uniform mat4 ModelViewMatrix;\n"
"void main(void)\n"
"{\n"
+" TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" gl_FrontColor = gl_Color;\n"
+" TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
+"#endif\n"
+"\n"
+" // transform unnormalized eye direction into tangent space\n"
"#ifdef USEOFFSETMAPPING\n"
-" // apply offsetmapping\n"
-" vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
-"#define TexCoord TexCoordOffset\n"
+" vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
"#endif\n"
"\n"
-" vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
-" //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-" vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
-" vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
-" // FIXME temporary hack to detect the case that the reflection\n"
-" // gets blackened at edges due to leaving the area that contains actual\n"
-" // content.\n"
-" // Remove this 'ack once we have a better way to stop this thing from\n"
-" // 'appening.\n"
-" float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-" gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
+" VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
+" VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
+" VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n"
+"#endif // VERTEX_SHADER\n"
"\n"
-"#else // !MODE_REFRACTION\n"
+"#ifdef FRAGMENT_SHADER\n"
"void main(void)\n"
"{\n"
"#ifdef USEOFFSETMAPPING\n"
"#define TexCoord TexCoordOffset\n"
"#endif\n"
"\n"
-" // combine the diffuse textures (base, pants, shirt)\n"
-" myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
-"#ifdef USECOLORMAPPING\n"
-" color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
+"#ifdef USEALPHAKILL\n"
+" if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
+" discard;\n"
"#endif\n"
+"\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
-" //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
-" //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
-" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
-" color.a = 1.0;\n"
-" //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
+" float alpha = texture2D(Texture_Color, TexCoord).a;\n"
+" float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
+" //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
+" //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
"#endif\n"
"\n"
-"#ifdef USEDIFFUSE\n"
-" // get the surface normal and the gloss color\n"
-"# ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
-"# ifdef USESPECULAR\n"
-" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
-"# endif\n"
-"# else\n"
-" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
-"# ifdef USESPECULAR\n"
-" myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
-"# endif\n"
-"# endif\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), a);\n"
+"}\n"
+"#endif // FRAGMENT_SHADER\n"
+"#else // !MODE_DEFERREDGEOMETRY\n"
"\n"
"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" // light source\n"
-"\n"
-" // calculate surface normal, light normal, and specular normal\n"
-" // compute color intensity for the two textures (colormap and glossmap)\n"
-" // scale by light color and attenuation as efficiently as possible\n"
-" // (do as much scalar math as possible rather than vector math)\n"
-"# ifdef USEDIFFUSE\n"
-" // get the light normal\n"
-" myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
-"# endif\n"
-"# ifdef USESPECULAR\n"
-"# ifndef USEEXACTSPECULARMATH\n"
-" myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
"\n"
-"# endif\n"
-" // calculate directional shading\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
-"# else\n"
-" color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
-"# endif\n"
-"# else\n"
-"# ifdef USEDIFFUSE\n"
-" // calculate directional shading\n"
-" color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
-"# else\n"
-" // calculate directionless shading\n"
-" color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
-"# endif\n"
-"# endif\n"
+"\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"#ifdef VERTEX_SHADER\n"
+"uniform mat4 ModelViewMatrix;\n"
+"void main(void)\n"
+"{\n"
+" ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
+"}\n"
+"#endif // VERTEX_SHADER\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"uniform mat4 ViewToLight;\n"
+"// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
+"uniform vec2 ScreenToDepth;\n"
+"uniform myhalf3 DeferredColor_Ambient;\n"
+"uniform myhalf3 DeferredColor_Diffuse;\n"
+"#ifdef USESPECULAR\n"
+"uniform myhalf3 DeferredColor_Specular;\n"
+"uniform myhalf SpecularPower;\n"
+"#endif\n"
+"uniform myhalf2 PixelToScreenTexCoord;\n"
+"void main(void)\n"
+"{\n"
+" // calculate viewspace pixel position\n"
+" vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
+" vec3 position;\n"
+" position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
+" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
+" // decode viewspace pixel normal\n"
+" myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
+" myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
+" // surfacenormal = pixel normal in viewspace\n"
+" // LightVector = pixel to light in viewspace\n"
+" // CubeVector = position in lightspace\n"
+" // eyevector = pixel to view in viewspace\n"
+" vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
+" myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
+"#ifdef USEDIFFUSE\n"
+" // calculate diffuse shading\n"
+" myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
+" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"#endif\n"
+"#ifdef USESPECULAR\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 * 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 * normalmap.a);\n"
+"# endif\n"
+"#endif\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
-"#if !showshadowmap\n"
-" color.rgb *= ShadowMapCompare(CubeVector);\n"
+" fade *= ShadowMapCompare(CubeVector);\n"
+"#endif\n"
+"\n"
+"#ifdef USEDIFFUSE\n"
+" gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
+"#else\n"
+" gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
"#endif\n"
+"#ifdef USESPECULAR\n"
+" gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
+"#else\n"
+" gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
"#endif\n"
"\n"
"# ifdef USECUBEFILTER\n"
-" // apply light cubemap filter\n"
-" //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
-" color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
+" vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
+" gl_FragData[0].rgb *= cubecolor;\n"
+" gl_FragData[1].rgb *= cubecolor;\n"
"# endif\n"
-"#endif // MODE_LIGHTSOURCE\n"
+"}\n"
+"#endif // FRAGMENT_SHADER\n"
+"#else // !MODE_DEFERREDLIGHTSOURCE\n"
"\n"
"\n"
"\n"
"\n"
-"#ifdef MODE_LIGHTDIRECTION\n"
-" // directional model lighting\n"
+"#ifdef VERTEX_SHADER\n"
+"uniform mat4 TexMatrix;\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"uniform mat4 BackgroundTexMatrix;\n"
+"#endif\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+"uniform mat4 ModelToLight;\n"
+"#endif\n"
+"void main(void)\n"
+"{\n"
+"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
+" gl_FrontColor = gl_Color;\n"
+"#endif\n"
+" // copy the surface texcoord\n"
+" TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
+"#endif\n"
+"#ifdef USELIGHTMAP\n"
+" TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
+"#endif\n"
+"\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+" // transform vertex position into light attenuation/cubemap space\n"
+" // (-1 to +1 across the light box)\n"
+" CubeVector = vec3(ModelToLight * gl_Vertex);\n"
+"\n"
"# ifdef USEDIFFUSE\n"
-" // get the light normal\n"
-" myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
+" // transform unnormalized light direction into tangent space\n"
+" // (we use unnormalized to ensure that it interpolates correctly and then\n"
+" // normalize it per pixel)\n"
+" vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
+" LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
+" LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
+" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
"# endif\n"
-"# ifdef USESPECULAR\n"
-" // calculate directional shading\n"
-" color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
-"# else\n"
-" myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
-" color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
-"# endif\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
+" LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
+" LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
+" LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
+" // transform unnormalized eye direction into tangent space\n"
+"#ifdef USEEYEVECTOR\n"
+" vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
+"#ifdef USEFOG\n"
+" EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
+" EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
+" VectorS = gl_MultiTexCoord1.xyz;\n"
+" VectorT = gl_MultiTexCoord2.xyz;\n"
+" VectorR = gl_MultiTexCoord3.xyz;\n"
+"#endif\n"
+"\n"
+" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
+" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
+"\n"
+"#ifdef USEREFLECTION\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"#endif\n"
+"}\n"
+"#endif // VERTEX_SHADER\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform myhalf2 PixelToScreenTexCoord;\n"
+"uniform myhalf3 DeferredMod_Diffuse;\n"
+"uniform myhalf3 DeferredMod_Specular;\n"
+"#endif\n"
+"uniform myhalf3 Color_Ambient;\n"
+"uniform myhalf3 Color_Diffuse;\n"
+"uniform myhalf3 Color_Specular;\n"
+"uniform myhalf SpecularPower;\n"
+"#ifdef USEGLOW\n"
+"uniform myhalf3 Color_Glow;\n"
+"#endif\n"
+"uniform myhalf Alpha;\n"
+"#ifdef USEREFLECTION\n"
+"uniform vec4 DistortScaleRefractReflect;\n"
+"uniform vec4 ScreenScaleRefractReflect;\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"
+"#ifdef MODE_LIGHTSOURCE\n"
+"uniform myhalf3 LightColor;\n"
+"#endif\n"
+"void main(void)\n"
+"{\n"
+"#ifdef USEOFFSETMAPPING\n"
+" // apply offsetmapping\n"
+" vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
+"#define TexCoord TexCoordOffset\n"
+"#endif\n"
+"\n"
+" // combine the diffuse textures (base, pants, shirt)\n"
+" myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
+"#ifdef USEALPHAKILL\n"
+" if (color.a < 0.5)\n"
+" discard;\n"
+"#endif\n"
+" color.a *= Alpha;\n"
+"#ifdef USECOLORMAPPING\n"
+" color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
+"#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
+" //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
+" //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
+" color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
+" color.a = 1.0;\n"
+" //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
+"#endif\n"
+"\n"
+" // get the surface normal\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
+"#else\n"
+" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
+"#endif\n"
+"\n"
+" // get the material colors\n"
+" myhalf3 diffusetex = color.rgb;\n"
+"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
+" myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
"# else\n"
-"# ifdef USEDIFFUSE\n"
+" myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
+"# endif\n"
+"#endif\n"
"\n"
-" // calculate directional shading\n"
-" color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
-"# else\n"
-" color.rgb *= AmbientColor;\n"
-"# endif\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"
+"#ifdef MODE_LIGHTSOURCE\n"
+" // light source\n"
+"#ifdef USEDIFFUSE\n"
+" myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
+" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\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 * 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 * glosstex.a);\n"
+"#endif\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
+"#endif\n"
+"#else\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
+"#endif\n"
+" color.rgb *= LightColor;\n"
+" color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
+"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
+" color.rgb *= ShadowMapCompare(CubeVector);\n"
+"#endif\n"
+"# ifdef USECUBEFILTER\n"
+" color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
"# endif\n"
-"#endif // MODE_LIGHTDIRECTION\n"
+"#endif // MODE_LIGHTSOURCE\n"
"\n"
"\n"
"\n"
"\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"#define SHADING\n"
+"#ifdef USEDIFFUSE\n"
+" myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
+"#endif\n"
+"#define lightcolor LightColor\n"
+"#endif // MODE_LIGHTDIRECTION\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-" // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
-"\n"
-" // get the light normal\n"
-" myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-" myhalf3 diffusenormal;\n"
-" diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
-" diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
-" diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
+"#define SHADING\n"
+" // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
+" myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
+" myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
+" // convert modelspace light vector to tangentspace\n"
+" myhalf3 lightnormal;\n"
+" lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
+" lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
+" lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
" // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
" // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
" // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
" // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
" // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
-" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
-" // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
-"# ifdef USESPECULAR\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
-"# else\n"
-" myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
-"# endif\n"
-"# endif\n"
-"\n"
-" // apply lightmap color\n"
-" color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
+" lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
-"\n"
-"\n"
-"\n"
-"\n"
"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
+"#define SHADING\n"
" // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
-"\n"
-" // get the light normal\n"
-" myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
-" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
-" myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
-"# ifdef USESPECULAR\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
-"# else\n"
-" myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
-" tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
-"# endif\n"
-"# endif\n"
-"\n"
-" // apply lightmap color\n"
-" color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
-"#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
+" myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
+" myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
+"#endif\n"
"\n"
"\n"
"\n"
"\n"
"#ifdef MODE_LIGHTMAP\n"
-" // apply lightmap color\n"
-" color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
+" color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
"#endif // MODE_LIGHTMAP\n"
-"\n"
-"\n"
-"\n"
-"\n"
"#ifdef MODE_VERTEXCOLOR\n"
-" // apply lightmap color\n"
-" color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
+" color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
"#endif // MODE_VERTEXCOLOR\n"
-"\n"
-"\n"
-"\n"
-"\n"
"#ifdef MODE_FLATCOLOR\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
"#endif // MODE_FLATCOLOR\n"
"\n"
"\n"
"\n"
"\n"
+"#ifdef SHADING\n"
+"# ifdef USEDIFFUSE\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 * 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 * glosstex.a);\n"
+"# endif\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"
+"# else\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
+"# endif\n"
+"#endif\n"
"\n"
-"\n"
-"\n"
-" color *= TintColor;\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.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+"#endif\n"
"\n"
"#ifdef USEGLOW\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-" color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
+" color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
"#else\n"
-" color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
+" color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
"#endif\n"
"#endif\n"
"\n"
-" color.rgb *= SceneBrightness;\n"
-"\n"
-" // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
"#ifdef USEFOG\n"
-" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+" color.rgb *= myhalf(FogVertex());\n"
"#else\n"
-" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+" color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
"#endif\n"
-"// float FogHeightFade1 = -0.5/1024.0;\n"
-"// if (FogPlaneViewDist >= 0.0)\n"
-"// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
-"// else\n"
-"// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
-"//# ifdef USEFOGABOVE\n"
-"// if (FogPlaneViewDist >= 0.0)\n"
-"// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
-"// else\n"
-"// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
-"// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
-"// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
-"// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
-"// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
-"\n"
-" //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
-" //float fade = -0.5/128.0;\n"
-" //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
-" //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
-" //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
-" //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
-" //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
-" //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
-" //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
-" //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
-"//# endif\n"
-" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\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"
" // content.\n"
" // Remove this 'ack once we have a better way to stop this thing from\n"
" // 'appening.\n"
-" float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
-" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
-" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-" color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
+" float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
+"#endif\n"
+"\n"
+" gl_FragColor = vec4(color);\n"
+"}\n"
+"#endif // FRAGMENT_SHADER\n"
+"\n"
+"#endif // !MODE_DEFERREDLIGHTSOURCE\n"
+"#endif // !MODE_DEFERREDGEOMETRY\n"
+"#endif // !MODE_WATER\n"
+"#endif // !MODE_REFRACTION\n"
+"#endif // !MODE_BLOOMBLUR\n"
+"#endif // !MODE_GENERIC\n"
+"#endif // !MODE_POSTPROCESS\n"
+"#endif // !MODE_SHOWDEPTH\n"
+"#endif // !MODE_DEPTH_OR_SHADOW\n"
+;
+
+/*
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+
+
+
+=========================================================================================================================================================
+*/
+
+const char *builtincgshaderstring =
+"// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
+"// written by Forest 'LordHavoc' Hale\n"
+"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
+"\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\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) || defined(USEREFLECTCUBE)\n"
+"#define USEEYEVECTOR\n"
+"#endif\n"
+"\n"
+"#ifdef MODE_DEPTH_OR_SHADOW\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"out float4 gl_Position : POSITION\n"
+")\n"
+"{\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_DEPTH_ORSHADOW\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_SHOWDEPTH\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float4 gl_FrontColor : COLOR0\n"
+")\n"
+"{\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+" gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_FrontColor : COLOR0,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" gl_FragColor = gl_FrontColor;\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_SHOWDEPTH\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_POSTPROCESS\n"
+"\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float2 TexCoord1 : TEXCOORD0,\n"
+"out float2 TexCoord2 : TEXCOORD1\n"
+")\n"
+"{\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+" TexCoord1 = gl_MultiTexCoord0.xy;\n"
+"#ifdef USEBLOOM\n"
+" TexCoord2 = gl_MultiTexCoord1.xy;\n"
+"#endif\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float2 TexCoord1 : TEXCOORD0,\n"
+"float2 TexCoord2 : TEXCOORD1,\n"
+"uniform sampler2D Texture_First,\n"
+"#ifdef USEBLOOM\n"
+"uniform sampler2D Texture_Second,\n"
+"#endif\n"
+"#ifdef USEGAMMARAMPS\n"
+"uniform sampler2D Texture_GammaRamps,\n"
+"#endif\n"
+"#ifdef USESATURATION\n"
+"uniform float Saturation,\n"
+"#endif\n"
+"#ifdef USEVIEWTINT\n"
+"uniform float4 ViewTintColor,\n"
+"#endif\n"
+"uniform float4 UserVec1,\n"
+"uniform float4 UserVec2,\n"
+"uniform float4 UserVec3,\n"
+"uniform float4 UserVec4,\n"
+"uniform float ClientTime,\n"
+"uniform float2 PixelSize,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
+"#ifdef USEBLOOM\n"
+" gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
+"#endif\n"
+"#ifdef USEVIEWTINT\n"
+" gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
+"#endif\n"
+"\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"
+" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
+" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
+" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
+" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
+" gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
+" gl_FragColor /= (1 + 5 * UserVec1.y);\n"
+"#endif\n"
+"\n"
+"#ifdef USESATURATION\n"
+" //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
+" float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
+" //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
+" gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
+"#endif\n"
+"\n"
+"#ifdef USEGAMMARAMPS\n"
+" gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
+" gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
+" gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
+"#endif\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_POSTPROCESS\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_GENERIC\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"float4 gl_Color : COLOR0,\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float4 gl_FrontColor : COLOR,\n"
+"out float2 TexCoord1 : TEXCOORD0,\n"
+"out float2 TexCoord2 : TEXCOORD1\n"
+")\n"
+"{\n"
+" gl_FrontColor = gl_Color;\n"
+"#ifdef USEDIFFUSE\n"
+" TexCoord1 = gl_MultiTexCoord0.xy;\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
+" TexCoord2 = gl_MultiTexCoord1.xy;\n"
+"#endif\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"\n"
+"void main\n"
+"(\n"
+"float4 gl_FrontColor : COLOR,\n"
+"float2 TexCoord1 : TEXCOORD0,\n"
+"float2 TexCoord2 : TEXCOORD1,\n"
+"#ifdef USEDIFFUSE\n"
+"uniform sampler2D Texture_First,\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
+"uniform sampler2D Texture_Second,\n"
+"#endif\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" gl_FragColor = gl_FrontColor;\n"
+"#ifdef USEDIFFUSE\n"
+" gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
+"#endif\n"
+"\n"
+"#ifdef USESPECULAR\n"
+" float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
+"# ifdef USECOLORMAPPING\n"
+" gl_FragColor *= tex2;\n"
+"# endif\n"
+"# ifdef USEGLOW\n"
+" gl_FragColor += tex2;\n"
+"# endif\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
+" gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
+"# endif\n"
+"#endif\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_GENERIC\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_BLOOMBLUR\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float2 TexCoord : TEXCOORD0\n"
+")\n"
+"{\n"
+" TexCoord = gl_MultiTexCoord0.xy;\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"\n"
+"void main\n"
+"(\n"
+"float2 TexCoord : TEXCOORD0,\n"
+"uniform sampler2D Texture_First,\n"
+"uniform float4 BloomBlur_Parameters,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" int i;\n"
+" float2 tc = TexCoord;\n"
+" float3 color = tex2D(Texture_First, tc).rgb;\n"
+" tc += BloomBlur_Parameters.xy;\n"
+" for (i = 1;i < SAMPLES;i++)\n"
+" {\n"
+" color += tex2D(Texture_First, tc).rgb;\n"
+" tc += BloomBlur_Parameters.xy;\n"
+" }\n"
+" gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_BLOOMBLUR\n"
+"#ifdef MODE_REFRACTION\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"uniform float4x4 TexMatrix,\n"
+"uniform float3 EyePosition,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float2 TexCoord : TEXCOORD0,\n"
+"out float3 EyeVector : TEXCOORD1,\n"
+"out float4 ModelViewProjectionPosition : TEXCOORD2\n"
+")\n"
+"{\n"
+" TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float2 TexCoord : TEXCOORD0,\n"
+"float3 EyeVector : TEXCOORD1,\n"
+"float4 ModelViewProjectionPosition : TEXCOORD2,\n"
+"uniform sampler2D Texture_Normal,\n"
+"uniform sampler2D Texture_Refraction,\n"
+"uniform sampler2D Texture_Reflection,\n"
+"uniform float4 DistortScaleRefractReflect,\n"
+"uniform float4 ScreenScaleRefractReflect,\n"
+"uniform float4 ScreenCenterRefractReflect,\n"
+"uniform float4 RefractColor,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
+" //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+" float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
+" float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_REFRACTION\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_WATER\n"
+"#ifdef VERTEX_SHADER\n"
+"\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"uniform float4x4 TexMatrix,\n"
+"uniform float3 EyePosition,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float2 TexCoord : TEXCOORD0,\n"
+"out float3 EyeVector : TEXCOORD1,\n"
+"out float4 ModelViewProjectionPosition : TEXCOORD2\n"
+")\n"
+"{\n"
+" TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
+" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float2 TexCoord : TEXCOORD0,\n"
+"float3 EyeVector : TEXCOORD1,\n"
+"float4 ModelViewProjectionPosition : TEXCOORD2,\n"
+"uniform sampler2D Texture_Normal,\n"
+"uniform sampler2D Texture_Refraction,\n"
+"uniform sampler2D Texture_Reflection,\n"
+"uniform float4 DistortScaleRefractReflect,\n"
+"uniform float4 ScreenScaleRefractReflect,\n"
+"uniform float4 ScreenCenterRefractReflect,\n"
+"uniform float4 RefractColor,\n"
+"uniform float4 ReflectColor,\n"
+"uniform float ReflectFactor,\n"
+"uniform float ReflectOffset,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
+" //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
+" f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
+" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
+" gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
+"}\n"
+"#endif\n"
+"#else // !MODE_WATER\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
+"\n"
+"// fragment shader specific:\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"
+"{\n"
+" float fogfrac;\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 float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
+"}\n"
+"#endif\n"
+"\n"
+"#ifdef USEOFFSETMAPPING\n"
+"float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
+"{\n"
+"#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
+" // 14 sample relief mapping: linear search and then binary search\n"
+" // this basically steps forward a small amount repeatedly until it finds\n"
+" // itself inside solid, then jitters forward and back using decreasing\n"
+" // amounts to find the impact\n"
+" //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
+" //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
+" float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
+" float3 RT = float3(TexCoord, 1);\n"
+" OffsetVector *= 0.1;\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
+" RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
+" RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
+" RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
+" RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
+" RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
+" return RT.xy;\n"
+"#else\n"
+" // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
+" // this basically moves forward the full distance, and then backs up based\n"
+" // on height of samples\n"
+" //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
+" //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
+" float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
+" TexCoord += OffsetVector;\n"
+" OffsetVector *= 0.333;\n"
+" TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
+" TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
+" TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
+" return TexCoord;\n"
+"#endif\n"
+"}\n"
+"#endif // USEOFFSETMAPPING\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\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"
+"# else\n"
+"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
+"{\n"
+" float3 adir = abs(dir);\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"
+"}\n"
+"# endif\n"
+"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
+"\n"
+"#ifdef USESHADOWMAPCUBE\n"
+"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
+"{\n"
+" float3 adir = abs(dir);\n"
+" return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+"}\n"
+"#endif\n"
+"\n"
+"# ifdef USESHADOWMAPRECT\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
+"#else\n"
+"float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
+"#endif\n"
+"{\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
+"#else\n"
+" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
+"#endif\n"
+" float f;\n"
+"# ifdef USESHADOWSAMPLER\n"
+"\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
+" f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# else\n"
+" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
+"# endif\n"
+"\n"
+"# else\n"
+"\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# if USESHADOWMAPPCF > 1\n"
+"# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
+" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
+" float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
+" float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
+" float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
+" float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
+" float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
+" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"# else\n"
+"# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
+" float2 offset = frac(shadowmaptc.xy);\n"
+" float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
+" float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
+" float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
+" float3 cols = row2 + lerp(row1, row3, offset.y);\n"
+" f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
+"# endif\n"
+"# else\n"
+" f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+"# endif\n"
+"\n"
+"# endif\n"
+" return f;\n"
+"}\n"
+"# endif\n"
+"\n"
+"# ifdef USESHADOWMAP2D\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
+"#else\n"
+"float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
+"#endif\n"
+"{\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
+"#else\n"
+" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
+"#endif\n"
+" float f;\n"
+"\n"
+"# ifdef USESHADOWSAMPLER\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
+" float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
+" f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
+"# else\n"
+" f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
+"# endif\n"
+"# else\n"
+"# ifdef USESHADOWMAPPCF\n"
+"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
+"# ifdef GL_ARB_texture_gather\n"
+"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
+"# else\n"
+"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
+"# endif\n"
+" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
+" float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
+" float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
+" float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
+" float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
+" lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
+" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"# else\n"
+"# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
+"# if USESHADOWMAPPCF > 1\n"
+" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
+" float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
+" float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
+" float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
+" float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
+" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"# else\n"
+" float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
+" float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
+" float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
+" float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
+" float3 cols = row2 + lerp(row1, row3, offset.y);\n"
+" f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
+"# endif\n"
+"# endif\n"
+"# else\n"
+" f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
+"# endif\n"
+"# endif\n"
+" return f;\n"
+"}\n"
+"# endif\n"
+"\n"
+"# ifdef USESHADOWMAPCUBE\n"
+"float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
+"{\n"
+" // apply depth texture cubemap as light filter\n"
+" float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
+" float f;\n"
+"# ifdef USESHADOWSAMPLER\n"
+" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
+"# else\n"
+" f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
+"# endif\n"
+" return f;\n"
+"}\n"
+"# endif\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // FRAGMENT_SHADER\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_DEFERREDGEOMETRY\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"float4 gl_Color : COLOR0,\n"
+"#endif\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
+"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
+"uniform float4x4 TexMatrix,\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
+"#endif\n"
+"uniform float4x4 ModelViewMatrix,\n"
+"#ifdef USEOFFSETMAPPING\n"
+"uniform float3 EyePosition,\n"
+"#endif\n"
+"out float4 gl_Position : POSITION,\n"
+"out float4 gl_FrontColor : COLOR,\n"
+"out float4 TexCoordBoth : TEXCOORD0,\n"
+"#ifdef USEOFFSETMAPPING\n"
+"out float3 EyeVector : TEXCOORD2,\n"
+"#endif\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"
+")\n"
+"{\n"
+" TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" gl_FrontColor = gl_Color;\n"
+" TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
+"#endif\n"
+"\n"
+" // transform unnormalized eye direction into tangent space\n"
+"#ifdef USEOFFSETMAPPING\n"
+" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
+" VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
+" VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
+" VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"}\n"
+"#endif // VERTEX_SHADER\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float4 TexCoordBoth : TEXCOORD0,\n"
+"float3 EyeVector : TEXCOORD2,\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"
+"uniform sampler2D Texture_Normal,\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"
+"#endif\n"
+"uniform half SpecularPower,\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" float2 TexCoord = TexCoordBoth.xy;\n"
+"#ifdef USEOFFSETMAPPING\n"
+" // apply offsetmapping\n"
+" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
+"#define TexCoord TexCoordOffset\n"
+"#endif\n"
+"\n"
+"#ifdef USEALPHAKILL\n"
+" if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
+" discard;\n"
+"#endif\n"
+"\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" float alpha = tex2D(Texture_Color, TexCoord).a;\n"
+" float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
+" //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
+" //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
+"#endif\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"
+"}\n"
+"#endif // FRAGMENT_SHADER\n"
+"#else // !MODE_DEFERREDGEOMETRY\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"uniform float4x4 ModelViewMatrix,\n"
+"out float4 gl_Position : POSITION,\n"
+"out float4 ModelViewPosition : TEXCOORD0\n"
+")\n"
+"{\n"
+" ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"}\n"
+"#endif // VERTEX_SHADER\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"float2 Pixel : WPOS,\n"
+"float4 ModelViewPosition : TEXCOORD0,\n"
+"uniform float4x4 ViewToLight,\n"
+"uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
+"uniform float3 LightPosition,\n"
+"uniform half2 PixelToScreenTexCoord,\n"
+"uniform half3 DeferredColor_Ambient,\n"
+"uniform half3 DeferredColor_Diffuse,\n"
+"#ifdef USESPECULAR\n"
+"uniform half3 DeferredColor_Specular,\n"
+"uniform half SpecularPower,\n"
+"#endif\n"
+"uniform sampler2D Texture_Attenuation,\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
+"\n"
+"#ifdef USESHADOWMAPRECT\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform samplerRECTShadow Texture_ShadowMapRect,\n"
+"# else\n"
+"uniform samplerRECT Texture_ShadowMapRect,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAP2D\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform sampler2DShadow Texture_ShadowMap2D,\n"
+"# else\n"
+"uniform sampler2D Texture_ShadowMap2D,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"uniform samplerCUBE Texture_CubeProjection,\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPCUBE\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
+"# else\n"
+"uniform samplerCUBE Texture_ShadowMapCube,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
+"uniform float2 ShadowMap_TextureScale,\n"
+"uniform float4 ShadowMap_Parameters,\n"
+"#endif\n"
+"\n"
+"out float4 gl_FragData0 : COLOR0,\n"
+"out float4 gl_FragData1 : COLOR1\n"
+")\n"
+"{\n"
+" // calculate viewspace pixel position\n"
+" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\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"
+" // decode viewspace pixel normal\n"
+" half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
+" half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
+" // surfacenormal = pixel normal in viewspace\n"
+" // LightVector = pixel to light in viewspace\n"
+" // CubeVector = position in lightspace\n"
+" // eyevector = pixel to view in viewspace\n"
+" float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
+" half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
+"#ifdef USEDIFFUSE\n"
+" // calculate diffuse shading\n"
+" half3 lightnormal = half3(normalize(LightPosition - position));\n"
+" half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"#endif\n"
+"#ifdef USESPECULAR\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 * 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 * normalmap.a);\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
+" fade *= ShadowMapCompare(CubeVector,\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"
+"# if defined(USESHADOWMAPCUBE)\n"
+"Texture_ShadowMapCube, ShadowMap_Parameters\n"
+"# endif\n"
+"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+", Texture_CubeProjection\n"
+"#endif\n"
+" );\n"
+"#endif\n"
+"\n"
+"#ifdef USEDIFFUSE\n"
+" gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
+"#else\n"
+" gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
+"#endif\n"
+"#ifdef USESPECULAR\n"
+" gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
+"#else\n"
+" gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
+"#endif\n"
+"\n"
+"# ifdef USECUBEFILTER\n"
+" float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
+" gl_FragData0.rgb *= cubecolor;\n"
+" gl_FragData1.rgb *= cubecolor;\n"
+"# endif\n"
+"}\n"
+"#endif // FRAGMENT_SHADER\n"
+"#else // !MODE_DEFERREDLIGHTSOURCE\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef VERTEX_SHADER\n"
+"void main\n"
+"(\n"
+"float4 gl_Vertex : POSITION,\n"
+"uniform float4x4 ModelViewProjectionMatrix,\n"
+"#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
+"float4 gl_Color : COLOR0,\n"
+"#endif\n"
+"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
+"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
+"float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
+"\n"
+"uniform float3 EyePosition,\n"
+"uniform float4x4 TexMatrix,\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
+"#endif\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+"uniform float4x4 ModelToLight,\n"
+"#endif\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+"uniform float3 LightPosition,\n"
+"#endif\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"uniform float3 LightDir,\n"
+"#endif\n"
+"uniform float4 FogPlane,\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform float3 LightPosition,\n"
+"#endif\n"
+"\n"
+"out float4 gl_FrontColor : COLOR,\n"
+"out float4 TexCoordBoth : TEXCOORD0,\n"
+"#ifdef USELIGHTMAP\n"
+"out float2 TexCoordLightmap : TEXCOORD1,\n"
+"#endif\n"
+"#ifdef USEEYEVECTOR\n"
+"out float3 EyeVector : TEXCOORD2,\n"
+"#endif\n"
+"#ifdef USEREFLECTION\n"
+"out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
+"#endif\n"
+"#ifdef USEFOG\n"
+"out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
+"#endif\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
+"out float3 LightVector : TEXCOORD5,\n"
+"#endif\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+"out float3 CubeVector : TEXCOORD3,\n"
+"#endif\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"
+"out float4 gl_Position : POSITION\n"
+")\n"
+"{\n"
+"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
+" gl_FrontColor = gl_Color;\n"
+"#endif\n"
+" // copy the surface texcoord\n"
+" TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
+"#endif\n"
+"#ifdef USELIGHTMAP\n"
+" TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
+"#endif\n"
+"\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+" // transform vertex position into light attenuation/cubemap space\n"
+" // (-1 to +1 across the light box)\n"
+" CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
+"\n"
+"# ifdef USEDIFFUSE\n"
+" // transform unnormalized light direction into tangent space\n"
+" // (we use unnormalized to ensure that it interpolates correctly and then\n"
+" // normalize it per pixel)\n"
+" float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
+" LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
+" LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
+" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
+" LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
+" LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
+" LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
+" // transform unnormalized eye direction into tangent space\n"
+"#ifdef USEEYEVECTOR\n"
+" float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
+" EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
+" EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
+" EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
+"#endif\n"
+"\n"
+"#ifdef USEFOG\n"
+" EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
+" EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
+"#endif\n"
+"\n"
+"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+" VectorS = gl_MultiTexCoord1.xyz;\n"
+" VectorT = gl_MultiTexCoord2.xyz;\n"
+" VectorR = gl_MultiTexCoord3.xyz;\n"
+"#endif\n"
+"\n"
+" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
+" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
+"\n"
+"#ifdef USEREFLECTION\n"
+" ModelViewProjectionPosition = gl_Position;\n"
+"#endif\n"
+"}\n"
+"#endif // VERTEX_SHADER\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"void main\n"
+"(\n"
+"#ifdef USEDEFERREDLIGHTMAP\n"
+"float2 Pixel : WPOS,\n"
+"#endif\n"
+"float4 gl_FrontColor : COLOR,\n"
+"float4 TexCoordBoth : TEXCOORD0,\n"
+"#ifdef USELIGHTMAP\n"
+"float2 TexCoordLightmap : TEXCOORD1,\n"
+"#endif\n"
+"#ifdef USEEYEVECTOR\n"
+"float3 EyeVector : TEXCOORD2,\n"
+"#endif\n"
+"#ifdef USEREFLECTION\n"
+"float4 ModelViewProjectionPosition : TEXCOORD3,\n"
+"#endif\n"
+"#ifdef USEFOG\n"
+"float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
+"#endif\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
+"float3 LightVector : TEXCOORD5,\n"
+"#endif\n"
+"#ifdef MODE_LIGHTSOURCE\n"
+"float3 CubeVector : TEXCOORD3,\n"
+"#endif\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"float4 ModelViewPosition : TEXCOORD0,\n"
+"#endif\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"
+"\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"
+"#endif\n"
+"#ifdef USECOLORMAPPING\n"
+"uniform sampler2D Texture_Pants,\n"
+"uniform sampler2D Texture_Shirt,\n"
+"#endif\n"
+"#ifdef USEFOG\n"
+"uniform sampler2D Texture_FogMask,\n"
+"#endif\n"
+"#ifdef USELIGHTMAP\n"
+"uniform sampler2D Texture_Lightmap,\n"
+"#endif\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
+"uniform sampler2D Texture_Deluxemap,\n"
+"#endif\n"
+"#ifdef USEREFLECTION\n"
+"uniform sampler2D Texture_Reflection,\n"
+"#endif\n"
+"\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
+"#endif\n"
+"#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform sampler2D Texture_ScreenDiffuse,\n"
+"uniform sampler2D Texture_ScreenSpecular,\n"
+"#endif\n"
+"\n"
+"#ifdef USECOLORMAPPING\n"
+"uniform half3 Color_Pants,\n"
+"uniform half3 Color_Shirt,\n"
+"#endif\n"
+"#ifdef USEFOG\n"
+"uniform float3 FogColor,\n"
+"uniform float FogRangeRecip,\n"
+"uniform float FogPlaneViewDist,\n"
+"uniform float FogHeightFade,\n"
+"#endif\n"
+"\n"
+"#ifdef USEOFFSETMAPPING\n"
+"uniform float OffsetMapping_Scale,\n"
+"#endif\n"
+"\n"
+"#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform half2 PixelToScreenTexCoord,\n"
+"uniform half3 DeferredMod_Diffuse,\n"
+"uniform half3 DeferredMod_Specular,\n"
+"#endif\n"
+"uniform half3 Color_Ambient,\n"
+"uniform half3 Color_Diffuse,\n"
+"uniform half3 Color_Specular,\n"
+"uniform half SpecularPower,\n"
+"#ifdef USEGLOW\n"
+"uniform half3 Color_Glow,\n"
+"#endif\n"
+"uniform half Alpha,\n"
+"#ifdef USEREFLECTION\n"
+"uniform float4 DistortScaleRefractReflect,\n"
+"uniform float4 ScreenScaleRefractReflect,\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"
+"#ifdef MODE_LIGHTSOURCE\n"
+"uniform half3 LightColor,\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"uniform sampler2D Texture_Attenuation,\n"
+"uniform samplerCUBE Texture_Cube,\n"
+"\n"
+"#ifdef USESHADOWMAPRECT\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform samplerRECTShadow Texture_ShadowMapRect,\n"
+"# else\n"
+"uniform samplerRECT Texture_ShadowMapRect,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAP2D\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform sampler2DShadow Texture_ShadowMap2D,\n"
+"# else\n"
+"uniform sampler2D Texture_ShadowMap2D,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+"uniform samplerCUBE Texture_CubeProjection,\n"
+"#endif\n"
+"\n"
+"#ifdef USESHADOWMAPCUBE\n"
+"# ifdef USESHADOWSAMPLER\n"
+"uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
+"# else\n"
+"uniform samplerCUBE Texture_ShadowMapCube,\n"
+"# endif\n"
+"#endif\n"
+"\n"
+"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
+"uniform float2 ShadowMap_TextureScale,\n"
+"uniform float4 ShadowMap_Parameters,\n"
+"#endif\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"\n"
+"out float4 gl_FragColor : COLOR\n"
+")\n"
+"{\n"
+" float2 TexCoord = TexCoordBoth.xy;\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" float2 TexCoord2 = TexCoordBoth.zw;\n"
+"#endif\n"
+"#ifdef USEOFFSETMAPPING\n"
+" // apply offsetmapping\n"
+" float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
+"#define TexCoord TexCoordOffset\n"
+"#endif\n"
+"\n"
+" // combine the diffuse textures (base, pants, shirt)\n"
+" half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
+"#ifdef USEALPHAKILL\n"
+" if (color.a < 0.5)\n"
+" discard;\n"
+"#endif\n"
+" color.a *= Alpha;\n"
+"#ifdef USECOLORMAPPING\n"
+" color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
+"#endif\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
+" //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
+" //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
+" color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
+" color.a = 1.0;\n"
+" //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
+"#endif\n"
+"\n"
+" // get the surface normal\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
+"#else\n"
+" half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
+"#endif\n"
+"\n"
+" // get the material colors\n"
+" half3 diffusetex = color.rgb;\n"
+"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
+"# ifdef USEVERTEXTEXTUREBLEND\n"
+" half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
+"# else\n"
+" half4 glosstex = half4(tex2D(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 = 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"
+"#ifdef MODE_LIGHTSOURCE\n"
+" // light source\n"
+"#ifdef USEDIFFUSE\n"
+" half3 lightnormal = half3(normalize(LightVector));\n"
+" half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\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 * 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 * glosstex.a);\n"
+"#endif\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
+"#endif\n"
+"#else\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
+"#endif\n"
+" color.rgb *= LightColor;\n"
+" color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
+"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
+" color.rgb *= ShadowMapCompare(CubeVector,\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"
+"# if defined(USESHADOWMAPCUBE)\n"
+"Texture_ShadowMapCube, ShadowMap_Parameters\n"
+"# endif\n"
+"\n"
+"#ifdef USESHADOWMAPVSDCT\n"
+", Texture_CubeProjection\n"
+"#endif\n"
+" );\n"
+"\n"
+"#endif\n"
+"# ifdef USECUBEFILTER\n"
+" color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
+"# endif\n"
+"#endif // MODE_LIGHTSOURCE\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_LIGHTDIRECTION\n"
+"#define SHADING\n"
+"#ifdef USEDIFFUSE\n"
+" half3 lightnormal = half3(normalize(LightVector));\n"
+"#endif\n"
+"#define lightcolor LightColor\n"
+"#endif // MODE_LIGHTDIRECTION\n"
+"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+"#define SHADING\n"
+" // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
+" half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
+" half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
+" // convert modelspace light vector to tangentspace\n"
+" half3 lightnormal;\n"
+" lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
+" lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
+" lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
+" // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
+" // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
+" // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
+" // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
+" // to map the luxels to coordinates on the draw surfaces), which also causes\n"
+" // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
+" // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
+" // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
+" // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
+" lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
+"#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+"#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
+"#define SHADING\n"
+" // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
+" half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
+" half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
+"#endif\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef MODE_LIGHTMAP\n"
+" color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
+"#endif // MODE_LIGHTMAP\n"
+"#ifdef MODE_VERTEXCOLOR\n"
+" color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
+"#endif // MODE_VERTEXCOLOR\n"
+"#ifdef MODE_FLATCOLOR\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
+"#endif // MODE_FLATCOLOR\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"#ifdef SHADING\n"
+"# ifdef USEDIFFUSE\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 * 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 * glosstex.a);\n"
+"# endif\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"
+"# else\n"
+" color.rgb = diffusetex * Color_Ambient;\n"
+"# endif\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.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
+"#endif\n"
+"\n"
+"#ifdef USEGLOW\n"
+"#ifdef USEVERTEXTEXTUREBLEND\n"
+" color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
+"#else\n"
+" color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
+"#endif\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"
+"#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"
+"#ifdef USEREFLECTION\n"
+" float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
+" //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
+" float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
+" // FIXME temporary hack to detect the case that the reflection\n"
+" // gets blackened at edges due to leaving the area that contains actual\n"
+" // content.\n"
+" // Remove this 'ack once we have a better way to stop this thing from\n"
+" // 'appening.\n"
+" float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
+" f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
+" ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
"#endif\n"
"\n"
-" gl_FragColor = vec4(color);\n"
-"\n"
-"#if showshadowmap\n"
-"# ifdef USESHADOWMAPRECT\n"
-"# ifdef USESHADOWSAMPLER\n"
-" gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
-"# else\n"
-" gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
-"# endif\n"
-"# endif\n"
-"# ifdef USESHADOWMAP2D\n"
-"# ifdef USESHADOWSAMPLER\n"
-" gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
-"# else\n"
-" gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
-"# endif\n"
-"# endif\n"
-"\n"
-"# ifdef USESHADOWMAPCUBE\n"
-"# ifdef USESHADOWSAMPLER\n"
-" gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
-"# else\n"
-" gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
-"# endif\n"
-"# endif\n"
-"#endif\n"
+" gl_FragColor = float4(color);\n"
"}\n"
-"#endif // !MODE_REFRACTION\n"
-"#endif // !MODE_WATER\n"
-"\n"
"#endif // FRAGMENT_SHADER\n"
"\n"
+"#endif // !MODE_DEFERREDLIGHTSOURCE\n"
+"#endif // !MODE_DEFERREDGEOMETRY\n"
+"#endif // !MODE_WATER\n"
+"#endif // !MODE_REFRACTION\n"
"#endif // !MODE_BLOOMBLUR\n"
"#endif // !MODE_GENERIC\n"
"#endif // !MODE_POSTPROCESS\n"
"#endif // !MODE_DEPTH_OR_SHADOW\n"
;
+char *glslshaderstring = NULL;
+char *cgshaderstring = NULL;
+
+//=======================================================================================================================================================
+
typedef struct shaderpermutationinfo_s
{
const char *pretext;
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_LIMIT = 1<<24, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
+ 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_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
{"#define USESHADOWSAMPLER\n", " shadowsampler"},
{"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
+ {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
+ {"#define USEALPHAKILL\n", " alphakill"},
+ {"#define USEREFLECTCUBE\n", " reflectcube"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
+ SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
+ SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
SHADERMODE_COUNT
}
shadermode_t;
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
-shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
+shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
{
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
{"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
+ {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
+};
+
+#ifdef SUPPORTCG
+shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
+{
+ {"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"},
+ {"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"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
+ {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
};
+#endif
struct r_glsl_permutation_s;
typedef struct r_glsl_permutation_s
int loc_Texture_ShadowMapCube;
int loc_Texture_ShadowMap2D;
int loc_Texture_CubeProjection;
- int loc_FogColor;
- int loc_LightPosition;
- int loc_EyePosition;
+ int loc_Texture_ScreenDepth;
+ 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_Color_Ambient;
+ int loc_Color_Diffuse;
+ int loc_Color_Specular;
+ int loc_Color_Glow;
int loc_Color_Pants;
int loc_Color_Shirt;
+ int loc_DeferredColor_Ambient;
+ int loc_DeferredColor_Diffuse;
+ int loc_DeferredColor_Specular;
+ int loc_DeferredMod_Diffuse;
+ int loc_DeferredMod_Specular;
+ int loc_DistortScaleRefractReflect;
+ int loc_EyePosition;
+ int loc_FogColor;
+ int loc_FogHeightFade;
int loc_FogPlane;
int loc_FogPlaneViewDist;
int loc_FogRangeRecip;
- int loc_FogHeightFade;
- int loc_AmbientScale;
- int loc_DiffuseScale;
- int loc_SpecularScale;
- int loc_SpecularPower;
- int loc_GlowColor;
- int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
- int loc_OffsetMapping_Scale;
- int loc_TintColor;
- int loc_AmbientColor;
- int loc_DiffuseColor;
- int loc_SpecularColor;
+ int loc_LightColor;
int loc_LightDir;
- int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
- int loc_GammaCoeff; ///< 1 / gamma
- int loc_DistortScaleRefractReflect;
- int loc_ScreenScaleRefractReflect;
- int loc_ScreenCenterRefractReflect;
- int loc_RefractColor;
+ int loc_LightPosition;
+ int loc_OffsetMapping_Scale;
+ int loc_PixelSize;
int loc_ReflectColor;
int loc_ReflectFactor;
int loc_ReflectOffset;
+ int loc_RefractColor;
+ int loc_Saturation;
+ int loc_ScreenCenterRefractReflect;
+ int loc_ScreenScaleRefractReflect;
+ int loc_ScreenToDepth;
+ int loc_ShadowMap_Parameters;
+ int loc_ShadowMap_TextureScale;
+ int loc_SpecularPower;
int loc_UserVec1;
int loc_UserVec2;
int loc_UserVec3;
int loc_UserVec4;
- int loc_ClientTime;
- int loc_PixelSize;
- int loc_Saturation;
- int loc_ShadowMap_TextureScale;
- int loc_ShadowMap_Parameters;
+ int loc_ViewTintColor;
+ int loc_ViewToLight;
+ int loc_ModelToLight;
+ int loc_TexMatrix;
+ int loc_BackgroundTexMatrix;
+ int loc_ModelViewProjectionMatrix;
+ int loc_ModelViewMatrix;
+ int loc_PixelToScreenTexCoord;
+ int loc_ModelToReflectCube;
}
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)
{
if (printfromdisknotice)
- Con_DPrint("from disk... ");
+ 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;
}
static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
{
int i;
- shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
+ shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
int vertstrings_count = 0;
int geomstrings_count = 0;
int fragstrings_count = 0;
geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
- strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
+ strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
// the first pretext is which type of shader to compile as
// (later these will all be bound together as a program object)
fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
// the second pretext is the mode (for example a light source)
- vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
- geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
- fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
+ vertstrings_list[vertstrings_count++] = modeinfo->pretext;
+ geomstrings_list[geomstrings_count++] = modeinfo->pretext;
+ fragstrings_list[fragstrings_count++] = modeinfo->pretext;
strlcat(permutationname, modeinfo->name, sizeof(permutationname));
// now add all the permutation pretexts
qglUseProgramObjectARB(p->program);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
+
p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
- p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ 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_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
- p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
+ p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
+ p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
- p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
- p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
- p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
+ p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
+ 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_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
+ p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
+ p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
+ p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
+ p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
+ p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
+ p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
+ p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
+ p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
+ p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
+ p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
+ p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
+ p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
- p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
- p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
- p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
- p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
- p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
- p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
- p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
- p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
- p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
- p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
- p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
- p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
+ p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
- p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
- p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
- p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
- p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
- p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
+ p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
+ p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
+ p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
- p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
+ p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
+ p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
+ p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
+ p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
+ p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
+ p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
+ p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
+ p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
- p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
- p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
- p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
- p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
- p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
+ p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
+ p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
+ p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
+ p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
+ p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
+ 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");
// 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_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
+ 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
- if (developer.integer)
- Con_Printf("GLSL shader %s compiled.\n", permutationname);
+ Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
}
else
- Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
+ Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
// free the strings
if (vertexstring)
Mem_Free(fragmentstring);
}
-void R_GLSL_Restart_f(void)
+void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
{
- unsigned int i, limit;
- r_glsl_permutation_t *p;
- limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
- for (i = 0;i < limit;i++)
+ r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
+ if (r_glsl_permutation != perm)
+ {
+ r_glsl_permutation = perm;
+ if (!r_glsl_permutation->program)
+ {
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(perm, mode, permutation);
+ if (!r_glsl_permutation->program)
+ {
+ // remove features until we find a valid permutation
+ int i;
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ {
+ // reduce i more quickly whenever it would not remove any bits
+ int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ if (!(permutation & j))
+ continue;
+ permutation -= j;
+ r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
+ if (!r_glsl_permutation->compiled)
+ R_GLSL_CompilePermutation(perm, mode, permutation);
+ if (r_glsl_permutation->program)
+ break;
+ }
+ if (i >= SHADERPERMUTATION_COUNT)
+ {
+ //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
+ r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ return; // no bit left to clear, entire mode is broken
+ }
+ }
+ }
+ CHECKGLERROR
+ qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
+ }
+ 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
+#include <Cg/cgGL.h>
+struct r_cg_permutation_s;
+typedef struct r_cg_permutation_s
+{
+ /// hash lookup data
+ struct r_cg_permutation_s *hashnext;
+ unsigned int mode;
+ unsigned int permutation;
+
+ /// indicates if we have tried compiling this permutation already
+ qboolean compiled;
+ /// 0 if compilation failed
+ CGprogram vprogram;
+ CGprogram fprogram;
+ /// locations of detected parameters in programs, or NULL if not found
+ CGparameter vp_EyePosition;
+ CGparameter vp_FogPlane;
+ CGparameter vp_LightDir;
+ CGparameter vp_LightPosition;
+ CGparameter vp_ModelToLight;
+ CGparameter vp_TexMatrix;
+ CGparameter vp_BackgroundTexMatrix;
+ CGparameter vp_ModelViewProjectionMatrix;
+ CGparameter vp_ModelViewMatrix;
+
+ CGparameter fp_Texture_First;
+ CGparameter fp_Texture_Second;
+ CGparameter fp_Texture_GammaRamps;
+ CGparameter fp_Texture_Normal;
+ CGparameter fp_Texture_Color;
+ CGparameter fp_Texture_Gloss;
+ CGparameter fp_Texture_Glow;
+ CGparameter fp_Texture_SecondaryNormal;
+ CGparameter fp_Texture_SecondaryColor;
+ CGparameter fp_Texture_SecondaryGloss;
+ CGparameter fp_Texture_SecondaryGlow;
+ CGparameter fp_Texture_Pants;
+ CGparameter fp_Texture_Shirt;
+ CGparameter fp_Texture_FogMask;
+ CGparameter fp_Texture_Lightmap;
+ CGparameter fp_Texture_Deluxemap;
+ CGparameter fp_Texture_Attenuation;
+ CGparameter fp_Texture_Cube;
+ CGparameter fp_Texture_Refraction;
+ CGparameter fp_Texture_Reflection;
+ CGparameter fp_Texture_ShadowMapRect;
+ CGparameter fp_Texture_ShadowMapCube;
+ CGparameter fp_Texture_ShadowMap2D;
+ CGparameter fp_Texture_CubeProjection;
+ CGparameter fp_Texture_ScreenDepth;
+ 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_Color_Ambient;
+ CGparameter fp_Color_Diffuse;
+ CGparameter fp_Color_Specular;
+ CGparameter fp_Color_Glow;
+ CGparameter fp_Color_Pants;
+ CGparameter fp_Color_Shirt;
+ CGparameter fp_DeferredColor_Ambient;
+ CGparameter fp_DeferredColor_Diffuse;
+ CGparameter fp_DeferredColor_Specular;
+ CGparameter fp_DeferredMod_Diffuse;
+ CGparameter fp_DeferredMod_Specular;
+ CGparameter fp_DistortScaleRefractReflect;
+ CGparameter fp_EyePosition;
+ CGparameter fp_FogColor;
+ CGparameter fp_FogHeightFade;
+ CGparameter fp_FogPlane;
+ CGparameter fp_FogPlaneViewDist;
+ CGparameter fp_FogRangeRecip;
+ CGparameter fp_LightColor;
+ CGparameter fp_LightDir;
+ CGparameter fp_LightPosition;
+ CGparameter fp_OffsetMapping_Scale;
+ CGparameter fp_PixelSize;
+ CGparameter fp_ReflectColor;
+ CGparameter fp_ReflectFactor;
+ CGparameter fp_ReflectOffset;
+ CGparameter fp_RefractColor;
+ CGparameter fp_Saturation;
+ CGparameter fp_ScreenCenterRefractReflect;
+ CGparameter fp_ScreenScaleRefractReflect;
+ CGparameter fp_ScreenToDepth;
+ CGparameter fp_ShadowMap_Parameters;
+ CGparameter fp_ShadowMap_TextureScale;
+ CGparameter fp_SpecularPower;
+ CGparameter fp_UserVec1;
+ CGparameter fp_UserVec2;
+ CGparameter fp_UserVec3;
+ CGparameter fp_UserVec4;
+ CGparameter fp_ViewTintColor;
+ CGparameter fp_ViewToLight;
+ CGparameter fp_PixelToScreenTexCoord;
+ CGparameter fp_ModelToReflectCube;
+}
+r_cg_permutation_t;
+
+/// information about each possible shader permutation
+r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
+/// currently selected permutation
+r_cg_permutation_t *r_cg_permutation;
+/// storage for permutations linked in the hash table
+memexpandablearray_t r_cg_permutationarray;
+
+#define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
+
+static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
+{
+ //unsigned int hashdepth = 0;
+ unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
+ r_cg_permutation_t *p;
+ for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
{
- if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
+ if (p->mode == mode && p->permutation == permutation)
{
- GL_Backend_FreeProgram(p->program);
- Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
+ //if (hashdepth > 10)
+ // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
+ return p;
}
+ //hashdepth++;
}
- memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
+ p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
+ p->mode = mode;
+ p->permutation = permutation;
+ p->hashnext = r_cg_permutationhash[mode][hashindex];
+ r_cg_permutationhash[mode][hashindex] = p;
+ //if (hashdepth > 10)
+ // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
+ return p;
+}
+
+static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
+{
+ 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)
+ {
+ if (printfromdisknotice)
+ Con_DPrintf("from disk %s... ", filename);
+ return shaderstring;
+ }
+ 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
}
-void R_GLSL_DumpShader_f(void)
-{
- int i;
+static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
+{
+ int i;
+ shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
+ int vertstrings_count = 0, vertstring_length = 0;
+ int geomstrings_count = 0, geomstring_length = 0;
+ int fragstrings_count = 0, fragstring_length = 0;
+ char *t;
+ char *vertexstring, *geometrystring, *fragmentstring;
+ char *vertstring, *geomstring, *fragstring;
+ const char *vertstrings_list[32+3];
+ const char *geomstrings_list[32+3];
+ const char *fragstrings_list[32+3];
+ char permutationname[256];
+ char cachename[256];
+ CGprofile vertexProfile;
+ CGprofile fragmentProfile;
+
+ if (p->compiled)
+ return;
+ p->compiled = true;
+ p->vprogram = NULL;
+ 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)
+ vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
+ geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
+ fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
+
+ // the second pretext is the mode (for example a light source)
+ vertstrings_list[vertstrings_count++] = modeinfo->pretext;
+ 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++)
+ {
+ if (permutation & (1<<i))
+ {
+ vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
+ 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
+ {
+ // keep line numbers correct
+ vertstrings_list[vertstrings_count++] = "\n";
+ geomstrings_list[geomstrings_count++] = "\n";
+ fragstrings_list[fragstrings_count++] = "\n";
+ }
+ }
+
+ // 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;
+ fragstrings_list[fragstrings_count++] = fragmentstring;
+
+ // if any sources were NULL, clear the respective list
+ if (!vertexstring)
+ vertstrings_count = 0;
+ if (!geometrystring)
+ geomstrings_count = 0;
+ if (!fragmentstring)
+ fragstrings_count = 0;
+
+ vertstring_length = 0;
+ for (i = 0;i < vertstrings_count;i++)
+ vertstring_length += strlen(vertstrings_list[i]);
+ vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
+ for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
+ memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
+
+ geomstring_length = 0;
+ for (i = 0;i < geomstrings_count;i++)
+ geomstring_length += strlen(geomstrings_list[i]);
+ geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
+ for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
+ memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
+
+ fragstring_length = 0;
+ for (i = 0;i < fragstrings_count;i++)
+ fragstring_length += strlen(fragstrings_list[i]);
+ fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
+ for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
+ memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
- qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
- if(!file)
- {
- Con_Printf("failed to write to glsl/default.glsl\n");
- return;
- }
+ CHECKGLERROR
+ CHECKCGERROR
+ //vertexProfile = CG_PROFILE_ARBVP1;
+ //fragmentProfile = CG_PROFILE_ARBFP1;
+ vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
+ fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
+ //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
+ //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
+ //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
+ CHECKGLERROR
- FS_Print(file, "/* The engine may define the following macros:\n");
- FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
- for (i = 0;i < SHADERMODE_COUNT;i++)
- FS_Print(file, shadermodeinfo[i].pretext);
- for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- FS_Print(file, shaderpermutationinfo[i].pretext);
- FS_Print(file, "*/\n");
- FS_Print(file, builtinshaderstring);
- FS_Close(file);
+ // 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
+ 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");
+ CHECKCGERROR
+ }
+ if (p->fprogram)
+ {
+ 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_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]))
+ Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
+ else
+ Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
- Con_Printf("glsl/default.glsl written\n");
+ // free the strings
+ if (vertstring)
+ Mem_Free(vertstring);
+ if (geomstring)
+ Mem_Free(geomstring);
+ if (fragstring)
+ Mem_Free(fragstring);
+ if (vertexstring)
+ Mem_Free(vertexstring);
+ if (geometrystring)
+ Mem_Free(geometrystring);
+ if (fragmentstring)
+ Mem_Free(fragmentstring);
}
-void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
+void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
{
- r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
- if (r_glsl_permutation != perm)
+ r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
+ CHECKGLERROR
+ CHECKCGERROR
+ if (r_cg_permutation != perm)
{
- r_glsl_permutation = perm;
- if (!r_glsl_permutation->program)
+ r_cg_permutation = perm;
+ if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
{
- if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(perm, mode, permutation);
- if (!r_glsl_permutation->program)
+ if (!r_cg_permutation->compiled)
+ R_CG_CompilePermutation(perm, mode, permutation);
+ if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
{
// remove features until we find a valid permutation
int i;
if (!(permutation & j))
continue;
permutation -= j;
- r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
- if (!r_glsl_permutation->compiled)
- R_GLSL_CompilePermutation(perm, mode, permutation);
- if (r_glsl_permutation->program)
+ r_cg_permutation = R_CG_FindPermutation(mode, permutation);
+ if (!r_cg_permutation->compiled)
+ R_CG_CompilePermutation(perm, mode, permutation);
+ if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
break;
}
if (i >= SHADERPERMUTATION_COUNT)
{
- Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
- r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
- qglUseProgramObjectARB(0);CHECKGLERROR
+ //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
+ r_cg_permutation = R_CG_FindPermutation(mode, permutation);
return; // no bit left to clear, entire mode is broken
}
}
}
CHECKGLERROR
- qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
+ CHECKCGERROR
+ if (r_cg_permutation->vprogram)
+ {
+ cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
+ cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ }
+ else
+ {
+ cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ }
+ if (r_cg_permutation->fprogram)
+ {
+ cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
+ cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+ }
+ else
+ {
+ cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+ cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+ }
}
+ 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)
+{
+ cgGLSetTextureParameter(param, R_GetTexture(tex));
+ cgGLEnableTextureParameter(param);
}
+#endif
-void R_SetupGenericShader(qboolean usetexture)
+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:
- R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
+ {
+ r_glsl_permutation_t *p;
+ r_glsl_permutation = NULL;
+ limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
+ for (i = 0;i < limit;i++)
+ {
+ if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
+ {
+ GL_Backend_FreeProgram(p->program);
+ Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
+ }
+ }
+ memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
+ }
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ {
+ r_cg_permutation_t *p;
+ r_cg_permutation = NULL;
+ cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+ cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
+ limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
+ for (i = 0;i < limit;i++)
+ {
+ if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
+ {
+ if (p->vprogram)
+ cgDestroyProgram(p->vprogram);
+ if (p->fprogram)
+ cgDestroyProgram(p->fprogram);
+ Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
+ }
+ }
+ memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
+ }
break;
+#endif
case RENDERPATH_GL13:
case RENDERPATH_GL11:
break;
}
}
-void R_SetupGenericTwoTextureShader(int texturemode)
+void R_GLSL_DumpShader_f(void)
+{
+ int i;
+ qfile_t *file;
+
+ file = FS_OpenRealFile("glsl/default.glsl", "w", false);
+ if (file)
+ {
+ FS_Print(file, "/* The engine may define the following macros:\n");
+ FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
+ for (i = 0;i < SHADERMODE_COUNT;i++)
+ FS_Print(file, glslshadermodeinfo[i].pretext);
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ FS_Print(file, shaderpermutationinfo[i].pretext);
+ FS_Print(file, "*/\n");
+ FS_Print(file, builtinshaderstring);
+ FS_Close(file);
+ Con_Printf("glsl/default.glsl written\n");
+ }
+ else
+ Con_Printf("failed to write to glsl/default.glsl\n");
+
+#ifdef SUPPORTCG
+ file = FS_OpenRealFile("cg/default.cg", "w", false);
+ if (file)
+ {
+ FS_Print(file, "/* The engine may define the following macros:\n");
+ FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
+ for (i = 0;i < SHADERMODE_COUNT;i++)
+ FS_Print(file, cgshadermodeinfo[i].pretext);
+ for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
+ FS_Print(file, shaderpermutationinfo[i].pretext);
+ FS_Print(file, "*/\n");
+ FS_Print(file, builtincgshaderstring);
+ FS_Close(file);
+ Con_Printf("cg/default.cg written\n");
+ }
+ else
+ Con_Printf("failed to write to cg/default.cg\n");
+#endif
+}
+
+void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
{
+ if (!second)
+ texturemode = GL_MODULATE;
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
+ R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
+ if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
+ if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ CHECKCGERROR
+ R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
+ if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
+#endif
break;
case RENDERPATH_GL13:
+ R_Mesh_TexBind(0, first );
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexBind(1, second);
+ if (second)
+ R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
+ break;
case RENDERPATH_GL11:
- R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
+ R_Mesh_TexBind(0, first );
break;
}
}
-void R_SetupDepthOrShadowShader(void)
+void R_SetupShader_DepthOrShadow(void)
{
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
+ R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
+#endif
break;
case RENDERPATH_GL13:
+ R_Mesh_TexBind(0, 0);
+ R_Mesh_TexBind(1, 0);
break;
case RENDERPATH_GL11:
+ R_Mesh_TexBind(0, 0);
break;
}
}
-void R_SetupShowDepthShader(void)
+void R_SetupShader_ShowDepth(void)
{
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
+ R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
+#endif
break;
case RENDERPATH_GL13:
break;
}
}
+extern qboolean r_shadow_usingdeferredprepass;
+extern cvar_t r_shadow_deferred_8bitrange;
extern rtexture_t *r_shadow_attenuationgradienttexture;
extern rtexture_t *r_shadow_attenuation2dtexture;
extern rtexture_t *r_shadow_attenuation3dtexture;
extern qboolean r_shadow_shadowmapvsdct;
extern qboolean r_shadow_shadowmapsampler;
extern int r_shadow_shadowmappcf;
-void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
+extern rtexture_t *r_shadow_shadowmaprectangletexture;
+extern rtexture_t *r_shadow_shadowmap2dtexture;
+extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
+extern rtexture_t *r_shadow_shadowmapvsdcttexture;
+extern int r_shadow_shadowmaplod; // changes for each light based on distance
+extern int r_shadow_prepass_width;
+extern int r_shadow_prepass_height;
+extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
+extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
+extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
+extern rtexture_t *r_shadow_prepasslightingspeculartexture;
+void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
{
// select a permutation of the lighting shader appropriate to this
// combination of texture, entity, light source, and fogging, only use the
// fragment shader on features that are not being used
unsigned int permutation = 0;
unsigned int mode = 0;
- // TODO: implement geometry-shader based shadow volumes someday
- if (r_glsl_offsetmapping.integer)
- {
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
- }
+ float m16f[16];
if (rsurfacepass == RSURFPASS_BACKGROUND)
{
// distorted background
mode = SHADERMODE_WATER;
else
mode = SHADERMODE_REFRACTION;
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest(false);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ }
+ else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
+ {
+ if (r_glsl_offsetmapping.integer)
+ {
+ 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->currentmaterialflags & MATERIALFLAG_ALPHATEST)
+ permutation |= SHADERPERMUTATION_ALPHAKILL;
+ // normalmap (deferred prepass), may use alpha test on diffuse
+ mode = SHADERMODE_DEFERREDGEOMETRY;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest(false);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
+ if (r_glsl_offsetmapping.integer)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
// light source
mode = SHADERMODE_LIGHTSOURCE;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
if (diffusescale > 0)
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
+ {
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ }
if (r_refdef.fogenabled)
permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
if (rsurface.texture->colormapping)
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))
+ {
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+ }
+ //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
- // unshaded geometry (fullbright or ambient model lighting)
- mode = SHADERMODE_FLATCOLOR;
+ if (r_glsl_offsetmapping.integer)
+ {
+ 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->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ // unshaded geometry (fullbright or ambient model lighting)
+ mode = SHADERMODE_FLATCOLOR;
+ ambientscale = diffusescale = specularscale = 0;
+ 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;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
+ 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))
+ {
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+ }
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ }
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
+ {
if (r_glsl_offsetmapping.integer)
{
permutation |= SHADERPERMUTATION_OFFSETMAPPING;
if (r_glsl_offsetmapping_reliefmapping.integer)
permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
}
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
- permutation |= SHADERPERMUTATION_REFLECTION;
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
- {
- // directional model lighting
- mode = SHADERMODE_LIGHTDIRECTION;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ // directional model lighting
+ mode = SHADERMODE_LIGHTDIRECTION;
+ if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
+ {
permutation |= SHADERPERMUTATION_SPECULAR;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ }
if (r_refdef.fogenabled)
permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
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))
+ {
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+ }
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
- // ambient model lighting
- mode = SHADERMODE_LIGHTDIRECTION;
+ if (r_glsl_offsetmapping.integer)
+ {
+ 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->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ // ambient model lighting
+ mode = SHADERMODE_LIGHTDIRECTION;
+ 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 |= SHADERPERMUTATION_COLORMAPPING;
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))
+ {
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+ }
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else
{
+ if (r_glsl_offsetmapping.integer)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
// lightmapped wall
+ 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;
+ if (rsurface.texture->colormapping)
+ permutation |= SHADERPERMUTATION_COLORMAPPING;
+ 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)
mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
+ {
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ }
+ R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (r_glsl_deluxemapping.integer >= 2)
{
mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
+ {
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ }
+ R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (rsurface.uselightmaptexture)
{
// ordinary lightmapping (q1bsp, q3bsp)
mode = SHADERMODE_LIGHTMAP;
+ R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ else
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ }
+ else
+ {
+ // ordinary vertex coloring (q3bsp)
+ mode = SHADERMODE_VERTEXCOLOR;
+ R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
+ R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
+ }
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
+ {
+ 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);
+ R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
+ }
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ }
+ switch(vid.renderpath)
+ {
+ 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);}
+ if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
+ if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
+ if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
+ if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
+
+ // 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 (mode == SHADERMODE_FLATCOLOR)
+ {
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
+ }
+ else if (mode == SHADERMODE_LIGHTDIRECTION)
+ {
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
+ if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
+ if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
+ if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
+ if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+ }
+ else
+ {
+ if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
+ if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
+ if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
+ if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
+ if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
+ }
+ // additive passes are only darkened by fog, not tinted
+ if (r_glsl_permutation->loc_FogColor >= 0)
+ {
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+ qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
+ else
+ qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
+ }
+ if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
+ if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
+ if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
+ if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
+ if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
+ if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
+ if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
+ if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
+ }
+ 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_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_Color_Pants >= 0)
+ {
+ if (rsurface.texture->pantstexture)
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+ else
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
}
- else
+ if (r_glsl_permutation->loc_Color_Shirt >= 0)
{
- // ordinary vertex coloring (q3bsp)
- mode = SHADERMODE_VERTEXCOLOR;
+ if (rsurface.texture->shirttexture)
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
+ else
+ qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
+ }
+ if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
+ 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_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_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
+ // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
+ // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
+ if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
+ if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
+ if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
+ if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
+ if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
+ if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
+ if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
+ 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_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_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
+ if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
+ if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
+ if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
+ 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 (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 (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
- permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
- permutation |= SHADERPERMUTATION_GLOW;
- if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
- if (rsurface.texture->colormapping)
- permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
- permutation |= SHADERPERMUTATION_REFLECTION;
- }
- if(permutation & SHADERPERMUTATION_SPECULAR)
- if(r_shadow_glossexact.integer)
- permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
- R_SetupShader_SetPermutation(mode, permutation);
- if (mode == SHADERMODE_LIGHTSOURCE)
- {
- if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
- if (permutation & SHADERPERMUTATION_DIFFUSE)
+ 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_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
- if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
- if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
- if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
+ if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
+ if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
}
else
{
- // ambient only is simpler
- if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
- if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
- if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
- if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
+ if (mode == SHADERMODE_LIGHTDIRECTION)
+ {
+ if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
+ }
}
- // 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]);
- }
- else
- {
- if (mode == SHADERMODE_LIGHTDIRECTION)
+ 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_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
+
+ if (mode == SHADERMODE_LIGHTSOURCE)
{
- if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
- if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
- if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
- if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
+ if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
+
+ // 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_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
- if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
- if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
+ if (mode == SHADERMODE_FLATCOLOR)
+ {
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
+ }
+ else if (mode == SHADERMODE_LIGHTDIRECTION)
+ {
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
+ }
+ else
+ {
+ if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
+ }
+ // additive passes are only darkened by fog, not tinted
+ if (r_cg_permutation->fp_FogColor)
+ {
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+ cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
+ else
+ cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
+ CHECKCGERROR
+ }
+ if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
+ if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
+ if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
+ if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
+ 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_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_Color_Pants)
+ {
+ if (rsurface.texture->pantstexture)
+ cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
+ else
+ cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
+ CHECKCGERROR
}
- if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
- if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
- // additive passes are only darkened by fog, not tinted
- if (r_glsl_permutation->loc_FogColor >= 0)
+ if (r_cg_permutation->fp_Color_Shirt)
{
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
- qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
+ if (rsurface.texture->shirttexture)
+ cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
else
- qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
- }
- if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
- if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
- if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
- if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
- if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
- if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
- if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
- }
- if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
- if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
- if (r_glsl_permutation->loc_Color_Pants >= 0)
- {
- if (rsurface.texture->currentskinframe->pants)
- qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
- else
- qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
- }
- if (r_glsl_permutation->loc_Color_Shirt >= 0)
- {
- if (rsurface.texture->currentskinframe->shirt)
- qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
- else
- qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
+ cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
+ CHECKCGERROR
+ }
+ if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
+ if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
+ if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
+ if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
+ if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
+ if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
+
+ // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
+ // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );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_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );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_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_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );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 (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
+ }
+
+ CHECKGLERROR
+#endif
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ break;
}
- if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
- 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(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
+}
+
+void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
+{
+ // select a permutation of the lighting shader appropriate to this
+ // combination of texture, entity, light source, and fogging, only use the
+ // minimum features necessary to avoid wasting rendering time in the
+ // fragment shader on features that are not being used
+ unsigned int permutation = 0;
+ unsigned int mode = 0;
+ const float *lightcolorbase = rtlight->currentcolor;
+ float ambientscale = rtlight->ambientscale;
+ float diffusescale = rtlight->diffusescale;
+ float specularscale = rtlight->specularscale;
+ // this is the location of the light in view space
+ vec3_t viewlightorigin;
+ // this transforms from view space (camera) to light space (cubemap)
+ matrix4x4_t viewtolight;
+ matrix4x4_t lighttoview;
+ float viewtolight16f[16];
+ float range = 1.0f / r_shadow_deferred_8bitrange.value;
+ // light source
+ mode = SHADERMODE_DEFERREDLIGHTSOURCE;
+ if (rtlight->currentcubemap != r_texture_whitecube)
+ permutation |= SHADERPERMUTATION_CUBEFILTER;
+ if (diffusescale > 0)
+ permutation |= SHADERPERMUTATION_DIFFUSE;
+ if (specularscale > 0)
{
- if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
+ permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
- else
+ if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
+ {
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+ if (r_shadow_usingshadowmapcube)
+ permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
+ else if(r_shadow_shadowmapvsdct)
+ permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
+ Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
+ Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
+ Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
+ Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
+ switch(vid.renderpath)
{
- if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutationGLSL(mode, permutation);
+ if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
+ if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
+ if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
+ if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
+ if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
+ 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 , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
+ 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_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
+ if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
+ if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
+ 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 );
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ R_SetupShader_SetPermutationCG(mode, permutation);
+ if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
+ if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredColor_Ambient ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredColor_Diffuse ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);CHECKCGERROR
+ if (r_cg_permutation->fp_DeferredColor_Specular ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);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, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
+ if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
+
+ if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );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_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
+#endif
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ break;
}
- if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
- CHECKGLERROR
}
#define SKINFRAME_HASH 1024
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;
}
}
unsigned char *pixels;
unsigned char *bumppixels;
unsigned char *basepixels = NULL;
- int basepixels_width;
- int basepixels_height;
+ int basepixels_width = 0;
+ int basepixels_height = 0;
skinframe_t *skinframe;
+ rtexture_t *ddsbase = NULL;
+ qboolean ddshasalpha = false;
+ float ddsavgcolor[4];
+ char basename[MAX_QPATH];
if (cls.state == ca_dedicated)
return NULL;
if (skinframe && skinframe->base)
return skinframe;
- basepixels = loadimagepixelsbgra(name, complain, true);
- if (basepixels == NULL)
- return NULL;
+ Image_StripImageExtension(name, basename, sizeof(basename));
+
+ // 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, r_texture_convertsRGB_skin.integer);
+ if (basepixels == NULL)
+ return NULL;
+ }
if (developer_loading.integer)
Con_Printf("loading skin \"%s\"\n", name);
skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
skinframe->stain = NULL;
skinframe->merged = NULL;
- skinframe->base = r_texture_notexture;
+ skinframe->base = NULL;
skinframe->pants = NULL;
skinframe->shirt = NULL;
- skinframe->nmap = r_texture_blanknormalmap;
+ skinframe->nmap = NULL;
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
- basepixels_width = image_width;
- basepixels_height = image_height;
- skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
-
- if (textureflags & TEXF_ALPHA)
+ if (ddsbase)
+ {
+ skinframe->base = ddsbase;
+ skinframe->hasalpha = ddshasalpha;
+ VectorCopy(ddsavgcolor, skinframe->avgcolor);
+ if (r_loadfog && skinframe->hasalpha)
+ skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
+ //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+ }
+ else
{
- for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
+ basepixels_width = image_width;
+ basepixels_height = image_height;
+ skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ if (textureflags & TEXF_ALPHA)
{
- if (basepixels[j] < 255)
+ for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
{
- skinframe->hasalpha = true;
- break;
+ if (basepixels[j] < 255)
+ {
+ skinframe->hasalpha = true;
+ break;
+ }
}
- }
- if (r_loadfog && skinframe->hasalpha)
- {
- // has transparent pixels
- pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
- for (j = 0;j < image_width * image_height * 4;j += 4)
+ if (r_loadfog && skinframe->hasalpha)
{
- pixels[j+0] = 255;
- pixels[j+1] = 255;
- pixels[j+2] = 255;
- pixels[j+3] = basepixels[j+3];
+ // has transparent pixels
+ pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
+ for (j = 0;j < image_width * image_height * 4;j += 4)
+ {
+ pixels[j+0] = 255;
+ pixels[j+1] = 255;
+ pixels[j+2] = 255;
+ pixels[j+3] = basepixels[j+3];
+ }
+ skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ Mem_Free(pixels);
}
- skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
- Mem_Free(pixels);
}
+ R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
+ //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+ if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
+ R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
+ if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
+ R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
}
- R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
- //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
+ if (r_loaddds)
+ {
+ if (r_loadnormalmap)
+ skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
+ skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
+ if (r_loadgloss)
+ 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)
+ 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);
skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
}
+ if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
+ R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
}
- // _luma is supported for tenebrae compatibility
- // (I think it's a very stupid name, but oh well)
+
+ // _luma is supported only for tenebrae compatibility
// _glow is the preferred name
- if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
- if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
- if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
- if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
+ 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)
+ R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
+ Mem_Free(pixels);pixels = NULL;
+ }
+
+ 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)
+ R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
+ Mem_Free(pixels);
+ pixels = NULL;
+ }
+
+ 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)
+ R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
+ Mem_Free(pixels);
+ pixels = NULL;
+ }
+
+ 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)
+ R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
+ Mem_Free(pixels);
+ 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->stain = NULL;
skinframe->merged = NULL;
- skinframe->base = r_texture_notexture;
+ skinframe->base = NULL;
skinframe->pants = NULL;
skinframe->shirt = NULL;
- skinframe->nmap = r_texture_blanknormalmap;
+ skinframe->nmap = NULL;
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->stain = NULL;
skinframe->merged = NULL;
- skinframe->base = r_texture_notexture;
+ skinframe->base = NULL;
skinframe->pants = NULL;
skinframe->shirt = NULL;
- skinframe->nmap = r_texture_blanknormalmap;
+ skinframe->nmap = NULL;
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->stain = NULL;
skinframe->merged = NULL;
- skinframe->base = r_texture_notexture;
+ skinframe->base = NULL;
skinframe->pants = NULL;
skinframe->shirt = NULL;
- skinframe->nmap = r_texture_blanknormalmap;
+ skinframe->nmap = NULL;
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
if (cls.state == ca_dedicated)
return NULL;
- skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
+ skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
skinframe->stain = NULL;
skinframe->merged = NULL;
- skinframe->base = r_texture_notexture;
+ skinframe->base = NULL;
skinframe->pants = NULL;
skinframe->shirt = NULL;
- skinframe->nmap = r_texture_blanknormalmap;
+ skinframe->nmap = NULL;
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)
}
}
+extern rtexture_t *loadingscreentexture;
void gl_main_start(void)
{
+ loadingscreentexture = NULL;
+ r_texture_blanknormalmap = NULL;
+ r_texture_white = NULL;
+ r_texture_grey128 = NULL;
+ r_texture_black = NULL;
+ r_texture_whitecube = NULL;
+ r_texture_normalizationcube = NULL;
+ r_texture_fogattenuation = 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;
+
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
Cvar_SetValueQuick(&r_textureunits, vid.texunits);
Cvar_SetValueQuick(&gl_combine, 1);
Cvar_SetValueQuick(&r_glsl, 1);
memset(&r_waterstate, 0, sizeof(r_waterstate));
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
+ 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_refdef.fogmasktable_density = 0;
}
-extern rtexture_t *loadingscreentexture;
void gl_main_shutdown(void)
{
R_AnimCache_Free();
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = 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));
Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
Cvar_RegisterVariable(&r_fog_exp2);
Cvar_RegisterVariable(&r_drawfog);
+ 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);
Cvar_RegisterVariable(&r_track_sprites_flags);
Cvar_RegisterVariable(&r_track_sprites_scalew);
Cvar_RegisterVariable(&r_track_sprites_scaleh);
+ Cvar_RegisterVariable(&r_overheadsprites_perspective);
+ Cvar_RegisterVariable(&r_overheadsprites_pushback);
}
extern void R_Textures_Init(void);
extern void Sbar_Init(void);
extern void R_LightningBeams_Init(void);
extern void Mod_RenderInit(void);
+extern void Font_Init(void);
void Render_Init(void)
{
gl_backend_init();
R_Textures_Init();
GL_Main_Init();
+ Font_Init();
GL_Draw_Init();
R_Shadow_Init();
R_Sky_Init();
void R_FrameData_Reset(void)
{
- if (r_framedata_base);
+ if (r_framedata_base)
Mem_Free(r_framedata_base);
r_framedata_base = NULL;
r_framedata_size = 0;
{
size_t wantedsize;
if (r_framedata_failed)
- Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value * 1.25f);
+ Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
wantedsize = bound(65536, wantedsize, 128*1024*1024);
if (r_framedata_size != wantedsize)
{
r_framedata_size = wantedsize;
- if (r_framedata_base);
+ if (r_framedata_base)
Mem_Free(r_framedata_base);
r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
}
//==================================================================================
-// LordHavoc: animcache written by Echon, refactored and reformatted by me
+// LordHavoc: animcache originally written by Echon, rewritten since then
/**
- * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
- * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
- * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
+ * Animation cache prevents re-generating mesh data for an animated model
+ * multiple times in one frame for lighting, shadowing, reflections, etc.
*/
-typedef struct r_animcache_entity_s
-{
- float *vertex3f;
- float *normal3f;
- float *svector3f;
- float *tvector3f;
-}
-r_animcache_entity_t;
-
-typedef struct r_animcache_s
-{
- r_animcache_entity_t entity[MAX_EDICTS];
- int maxindex;
- int currentindex;
-}
-r_animcache_t;
-
-static r_animcache_t r_animcachestate;
-
void R_AnimCache_Free(void)
{
- memset(&r_animcachestate, 0, sizeof(r_animcachestate));
}
void R_AnimCache_ClearCache(void)
int i;
entity_render_t *ent;
- r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
- r_animcachestate.currentindex = 0;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
- ent->animcacheindex = -1;
+ ent->animcache_vertex3f = NULL;
+ ent->animcache_normal3f = NULL;
+ ent->animcache_svector3f = NULL;
+ ent->animcache_tvector3f = NULL;
}
}
qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
{
dp_model_t *model = ent->model;
- r_animcache_entity_t *c;
int numvertices;
// see if it's already cached this frame
- if (ent->animcacheindex >= 0)
+ if (ent->animcache_vertex3f)
{
// add normals/tangents if needed
if (wantnormals || wanttangents)
{
- c = r_animcachestate.entity + ent->animcacheindex;
- if (c->normal3f)
+ if (ent->animcache_normal3f)
wantnormals = false;
- if (c->svector3f)
+ if (ent->animcache_svector3f)
wanttangents = false;
if (wantnormals || wanttangents)
{
numvertices = model->surfmesh.num_vertices;
if (wantnormals)
- c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
if (wanttangents)
{
- c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
- c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
- model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
+ model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
}
}
}
else
{
// see if this ent is worth caching
- if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
- return false;
if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
return false;
- // assign it a cache entry and get some temp memory
- ent->animcacheindex = r_animcachestate.currentindex++;
- c = r_animcachestate.entity + ent->animcacheindex;
+ // get some memory for this entity and generate mesh data
numvertices = model->surfmesh.num_vertices;
- memset(c, 0, sizeof(*c));
- c->vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
if (wantnormals)
- c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
if (wanttangents)
{
- c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
- c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
+ ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
- model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, c->normal3f, c->svector3f, c->tvector3f);
+ model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
}
return !r_framedata_failed;
}
void R_AnimCache_CacheVisibleEntities(void)
{
int i;
- entity_render_t *ent;
qboolean wantnormals = !r_showsurfaces.integer;
qboolean wanttangents = !r_showsurfaces.integer;
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
}
// TODO: thread this
+ // NOTE: R_PrepareRTLights() also caches entities
for (i = 0;i < r_refdef.scene.numentities;i++)
- {
- if (!r_refdef.viewcache.entityvisible[i])
- continue;
- ent = r_refdef.scene.entities[i];
- if (ent->animcacheindex >= 0)
- continue;
- R_AnimCache_GetEntity(ent, wantnormals, wanttangents);
- }
+ 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);
}
//==================================================================================
}
// fetch the lighting from the worldmodel data
- VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
+ VectorClear(ent->modellight_ambient);
VectorClear(ent->modellight_diffuse);
VectorClear(tempdiffusenormal);
if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
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;
- if (!r_drawentities.integer)
- return;
-
renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
+ if (!r_drawviewmodel.integer)
+ renderimask |= RENDER_VIEWMODEL;
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
int i, sky;
entity_render_t *ent;
- if (!r_drawentities.integer)
- return false;
-
sky = false;
for (i = 0;i < r_refdef.scene.numentities;i++)
{
int i;
entity_render_t *ent;
- if (!r_drawentities.integer)
- return;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
int i;
entity_render_t *ent;
- if (!r_drawentities.integer)
- return;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
int i;
entity_render_t *ent;
- if (!r_drawentities.integer)
- return;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
int i;
entity_render_t *ent;
- if (!r_drawentities.integer)
- return;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
void R_SetupView(qboolean allowwaterclippingplane)
{
- const double *customclipplane = NULL;
- double plane[4];
+ const float *customclipplane = NULL;
+ float plane[4];
if (r_refdef.view.useclipplane && allowwaterclippingplane)
{
// LordHavoc: couldn't figure out how to make this approach the
R_SetViewport(&r_refdef.view.viewport);
}
+void R_EntityMatrix(const matrix4x4_t *matrix)
+{
+ if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
+ {
+ gl_modelmatrixchanged = false;
+ gl_modelmatrix = *matrix;
+ Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
+ Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
+ Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
+ Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
+ CHECKGLERROR
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
+ if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+ qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ CHECKCGERROR
+ if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
+ if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
+ qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
+#endif
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
+ break;
+ }
+ }
+}
+
void R_ResetViewRendering2D(void)
{
r_viewport_t viewport;
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_DepthTest(false);
- R_Mesh_Matrix(&identitymatrix);
+ R_EntityMatrix(&identitymatrix);
R_Mesh_ResetTextureState();
GL_PolygonOffset(0, 0);
qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
- R_SetupGenericShader(true);
}
void R_ResetViewRendering3D(void)
GL_DepthMask(true);
GL_DepthRange(0, 1);
GL_DepthTest(true);
- R_Mesh_Matrix(&identitymatrix);
+ R_EntityMatrix(&identitymatrix);
R_Mesh_ResetTextureState();
GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
GL_CullFace(r_refdef.view.cullface_back);
- R_SetupGenericShader(true);
}
void R_RenderScene(void);
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
if (!p->texture_refraction)
- p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
if (!p->texture_refraction)
goto error;
}
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
if (!p->texture_reflection)
- p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
if (!p->texture_reflection)
goto error;
}
r_waterstate.renderingscene = true;
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
{
- // render the normal view scene and copy into texture
- // (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_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;
- PlaneClassify(&r_refdef.view.clipplane);
-
- R_ResetViewRendering3D();
- R_ClearScreen(r_refdef.fogenabled);
- R_View_Update();
- R_RenderScene();
-
- // copy view into the screen texture
- R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
- }
-
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
r_refdef.view = myview;
R_View_Update();
R_RenderScene();
- R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ }
+
+ // render the normal view scene and copy into texture
+ // (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_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;
+ PlaneClassify(&r_refdef.view.clipplane);
+
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
+ 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.renderingscene = false;
r_refdef.view = originalview;
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
r_bloomstate.screentexturewidth = screentexturewidth;
r_bloomstate.screentextureheight = screentextureheight;
if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
- r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
}
if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
{
r_bloomstate.bloomtexturewidth = bloomtexturewidth;
r_bloomstate.bloomtextureheight = bloomtextureheight;
if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
- r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+ r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
}
// when doing a reduced render (HDR) we want to use a smaller area
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
// TODO: optimize with multitexture or GLSL
- R_SetupGenericShader(true);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
// we now have a bloom image in the framebuffer
// copy it into the bloom image texture for later processing
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
void R_Bloom_CopyHDRTexture(void)
{
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
- R_SetupGenericShader(true);
// we have a bloom image in the framebuffer
CHECKGLERROR
r = bound(0, r_bloom_colorexponent.value / x, 1);
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
GL_Color(r, r, r, 1);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
// copy the vertically blurred bloom view to a texture
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
brighten = sqrt(brighten);
if(range >= 1)
brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
for (dir = 0;dir < 2;dir++)
}
// copy the vertically blurred bloom view to a texture
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
{
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
+ R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
GL_Color(1, 1, 1, 1);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
GL_BlendFunc(GL_ONE, GL_ONE);
qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
- R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
qglBlendEquationEXT(GL_FUNC_ADD_EXT);
// copy the darkened bloom view to a texture
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
- GL_ActiveTexture(0);
- CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
}
}
static void R_BlendView(void)
{
unsigned int permutation;
+ float uservecs[4][4];
switch (vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
permutation =
(r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
- GL_ActiveTexture(0);CHECKGLERROR
if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
{
// apply the blur
if (cl.motionbluralpha > 0)
{
- R_SetupGenericShader(true);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(1, 1, 1, cl.motionbluralpha);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
+ R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
// copy view into the screen texture
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
+ R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
else if (!r_bloomstate.texture_bloom)
+ {
+ // we may still have to do view tint...
+ if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
+ {
+ // apply a color tint to the whole view
+ R_ResetViewRendering2D();
+ R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ }
break; // no screen processing, no bloom, skip it
+ }
if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
{
R_Bloom_MakeTexture();
}
+#if _MSC_VER >= 1400
+#define sscanf sscanf_s
+#endif
+ memset(uservecs, 0, sizeof(uservecs));
+ sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
+ sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
+ sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
+ sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
+
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
GL_Color(1, 1, 1, 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
- R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
- if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
- R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
- if (r_glsl_permutation->loc_TintColor >= 0)
- qglUniform4fARB(r_glsl_permutation->loc_TintColor, 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)
- {
- float a=0, b=0, c=0, d=0;
-#if _MSC_VER >= 1400
-#define sscanf sscanf_s
-#endif
- sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
- qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
- }
- if (r_glsl_permutation->loc_UserVec2 >= 0)
- {
- float a=0, b=0, c=0, d=0;
- sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
- qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
- }
- if (r_glsl_permutation->loc_UserVec3 >= 0)
- {
- float a=0, b=0, c=0, d=0;
- sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
- qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
- }
- if (r_glsl_permutation->loc_UserVec4 >= 0)
+
+ switch(vid.renderpath)
{
- float a=0, b=0, c=0, d=0;
- sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
- qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
+ case RENDERPATH_GL20:
+ R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
+ if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
+ 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_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_glsl_permutation->loc_UserVec3 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
+ if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
+ if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
+ if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
+ break;
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
+ if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
+ 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_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
+ if (r_cg_permutation->fp_UserVec3 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
+ if (r_cg_permutation->fp_UserVec4 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
+ if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
+ if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
+#endif
+ break;
+ default:
+ break;
}
- if (r_glsl_permutation->loc_Saturation >= 0)
- qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
break;
R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
{
R_Textures_Frame();
- r_refdef.scene.ambient = r_ambient.value;
+ r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
r_refdef.farclip = r_farclip_base.value;
if (r_refdef.scene.worldmodel)
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
if(v_glslgamma.integer && !vid_gammatables_trivial)
{
if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
}
else
{
- r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
}
}
}
{
if (r_timereport_active)
R_TimeReport("start");
- r_frame++; // used only by R_GetCurrentTexture
+ r_textureframe++; // used only by R_GetCurrentTexture
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ if (!r_drawentities.integer)
+ r_refdef.scene.numentities = 0;
+
R_AnimCache_ClearCache();
R_FrameData_NewFrame();
// this produces a bloom texture to be used in R_BlendView() later
if (r_hdr.integer && r_bloomstate.bloomwidth)
+ {
R_HDR_RenderBloomTexture();
+ // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
+ r_textureframe++; // used only by R_GetCurrentTexture
+ }
r_refdef.view.showdebug = true;
static void R_DrawEntityBBoxes(void);
static void R_DrawModelDecals(void);
extern cvar_t cl_decals_newsystem;
+extern qboolean r_shadow_usingdeferredprepass;
void R_RenderScene(void)
{
r_refdef.stats.renders++;
if (skyrendermasked && skyrenderlater)
{
// we have to force off the water clipping plane while rendering sky
+ qboolean save = r_refdef.view.showdebug;
R_SetupView(false);
+ r_refdef.view.showdebug = false;
R_Sky();
+ r_refdef.view.showdebug = save;
R_SetupView(true);
+ if (r_timereport_active)
+ R_TimeReport("sky");
}
}
R_AnimCache_CacheVisibleEntities();
- R_PrepareRTLights();
+ if (r_timereport_active)
+ R_TimeReport("animation");
+
+ R_Shadow_PrepareLights();
+ if (r_timereport_active)
+ R_TimeReport("preparelights");
+
+ if (r_shadow_usingdeferredprepass)
+ R_Shadow_DrawPrepass();
if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
{
S_ExtraUpdate ();
}
- R_ShadowVolumeLighting(false);
- if (r_timereport_active)
- R_TimeReport("rtlights");
+ if (!r_shadow_usingdeferredprepass)
+ {
+ R_Shadow_DrawLights();
+ if (r_timereport_active)
+ R_TimeReport("rtlights");
+ }
// don't let sound skip if going slow
if (r_refdef.scene.extraupdate)
R_TimeReport("lightning");
}
- R_SetupGenericShader(true);
VM_CL_AddPolygonsToMeshQueue();
if (r_refdef.view.showdebug)
}
}
- R_SetupGenericShader(true);
R_MeshQueue_RenderTransparent();
if (r_timereport_active)
R_TimeReport("drawtrans");
- R_SetupGenericShader(true);
-
if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
{
r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
R_TimeReport("modeldebug");
}
- R_SetupGenericShader(true);
-
if (cl.csqc_vidvars.drawworld)
{
- R_DrawCoronas();
+ R_Shadow_DrawCoronas();
if (r_timereport_active)
R_TimeReport("coronas");
}
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(color4f, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
}
return;
GL_CullFace(GL_NONE);
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
prog = 0;
SV_VM_Begin();
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
GL_DepthMask(false);
}
- else if (rsurface.ent_color[3] < 1)
+ else if (rsurface.colormod[3] < 1)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthMask(false);
GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
R_Mesh_ColorPointer(color4f, 0, 0);
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
- c[0] *= rsurface.ent_color[0];
- c[1] *= rsurface.ent_color[1];
- c[2] *= rsurface.ent_color[2];
- c[3] *= rsurface.ent_color[3];
+ c[0] *= rsurface.colormod[0];
+ c[1] *= rsurface.colormod[1];
+ c[2] *= rsurface.colormod[2];
+ c[3] *= rsurface.colormod[3];
}
if (r_refdef.fogenabled)
{
layer->blendfunc2 = blendfunc2;
layer->texture = texture;
layer->texmatrix = *matrix;
- layer->color[0] = r * r_refdef.view.colorscale;
- layer->color[1] = g * r_refdef.view.colorscale;
- layer->color[2] = b * r_refdef.view.colorscale;
+ layer->color[0] = r;
+ layer->color[1] = g;
+ layer->color[2] = b;
layer->color[3] = a;
}
void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
{
- int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
+ int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
char name[MAX_QPATH];
skinframe_t *skinframe;
unsigned char pixels[296*194];
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);
}
dp_model_t *model = ent->model;
q3shaderinfo_layer_tcmod_t *tcmod;
- if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
+ if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
return t->currentframe;
- t->update_lastrenderframe = r_frame;
+ t->update_lastrenderframe = r_textureframe;
t->update_lastrenderentity = (void *)ent;
// switch to an alternate material if this is a q1bsp animated material
t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
t->currentmaterialflags = t->basematerialflags;
- t->currentalpha = rsurface.ent_color[3];
+ t->currentalpha = rsurface.colormod[3];
if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
t->currentalpha *= r_wateralpha.value;
if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
if (!(rsurface.ent_flags & RENDER_LIGHT))
t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
- else if (rsurface.modeltexcoordlightmap2f == NULL)
+ else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
{
// pick a model lighting mode
if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
}
else
t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
+ if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
+ t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
// there is no tcmod
if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
if (t->currentskinframe->qpixels)
R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
+ if (!t->basetexture)
+ t->basetexture = r_texture_notexture;
+ t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
+ t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
+ t->nmaptexture = t->currentskinframe->nmap;
+ if (!t->nmaptexture)
+ t->nmaptexture = r_texture_blanknormalmap;
t->glosstexture = r_texture_black;
- t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
- t->backgroundglosstexture = 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->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
+ t->backgroundglosstexture = r_texture_black;
+ t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
+ if (!t->backgroundnmaptexture)
+ t->backgroundnmaptexture = r_texture_blanknormalmap;
+ }
+ else
+ {
+ t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
+ t->backgroundnmaptexture = r_texture_blanknormalmap;
+ t->backgroundglosstexture = r_texture_black;
+ t->backgroundglowtexture = NULL;
+ }
t->specularpower = r_shadow_glossexponent.value;
// TODO: store reference values for these in the texture?
t->specularscale = 0;
if (gl_lightmaps.integer)
{
t->basetexture = r_texture_grey128;
+ t->pantstexture = r_texture_black;
+ t->shirttexture = r_texture_black;
+ t->nmaptexture = r_texture_blanknormalmap;
+ 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;
+ t->backgroundglowtexture = NULL;
t->specularscale = 0;
t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
}
- Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
+ Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
VectorClear(t->dlightcolor);
t->currentnumlayers = 0;
if (t->currentmaterialflags & MATERIALFLAG_WALL)
{
- int layerflags = 0;
int blendfunc1, blendfunc2;
qboolean depthmask;
if (t->currentmaterialflags & MATERIALFLAG_ADD)
blendfunc2 = GL_ZERO;
}
depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
- if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
- layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
// fullbright is not affected by r_refdef.lightmapintensity
R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
- if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
- if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
}
else
{
vec3_t ambientcolor;
float colorscale;
// set the color tint used for lights affecting this surface
- VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
+ VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
colorscale = 2;
// q3bsp has no lightmap updates, so the lightstylevalue that
// would normally be baked into the lightmap must be
if (model->type == mod_brushq3)
colorscale *= r_refdef.scene.rtlightstylevalue[0];
colorscale *= r_refdef.lightmapintensity;
- VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
+ VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
// basic lit geometry
R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
// add pants/shirt if needed
- if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
- if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
// now add ambient passes if needed
if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
{
R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
- if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
- if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
+ if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
}
}
- if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
+ if (t->glowtexture != NULL && !gl_lightmaps.integer)
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
{
// if this is opaque use alpha blend which will darken the earlier
// were darkened by fog already, and we should not add fog color
// (because the background was not darkened, there is no fog color
// that was lost behind it).
- R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
+ R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
}
}
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = 0;
- Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
rsurface.ent_flags = r_refdef.scene.worldentity->flags;
if (rsurface.array_size < model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
rsurface.inversematrix = identitymatrix;
rsurface.matrixscale = 1;
rsurface.inversematrixscale = 1;
- R_Mesh_Matrix(&identitymatrix);
+ R_EntityMatrix(&identitymatrix);
VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
rsurface.fograngerecip = r_refdef.fograngerecip;
VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
- VectorSet(rsurface.glowmod, 1, 1, 1);
+ VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
+ rsurface.colormod[3] = 1;
+ VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
rsurface.frameblend[0].lerp = 1;
rsurface.ent_alttextures = false;
rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
}
-void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
+void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
{
dp_model_t *model = ent->model;
//if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
rsurface.ent_skinnum = ent->skinnum;
rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
rsurface.ent_shadertime = ent->shadertime;
- Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
rsurface.ent_flags = ent->flags;
if (rsurface.array_size < model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
rsurface.inversematrix = ent->inversematrix;
rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
- R_Mesh_Matrix(&rsurface.matrix);
+ R_EntityMatrix(&rsurface.matrix);
Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
- VectorCopy(ent->glowmod, rsurface.glowmod);
+ VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
+ rsurface.colormod[3] = ent->alpha;
+ VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
- if (ent->model->brush.submodel)
+ if (ent->model->brush.submodel && !prepass)
{
rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
}
if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
{
- if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
+ if (ent->animcache_vertex3f && !r_framedata_failed)
{
- rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
- rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
- rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
- rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
+ rsurface.modelvertex3f = ent->animcache_vertex3f;
+ rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
+ rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
+ rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
}
else if (wanttangents)
{
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = shadertime;
- Vector4Set(rsurface.ent_color, r, g, b, a);
rsurface.ent_flags = entflags;
rsurface.modelnum_vertices = numvertices;
rsurface.modelnum_triangles = numtriangles;
rsurface.inversematrix = *inversematrix;
rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
- R_Mesh_Matrix(&rsurface.matrix);
+ R_EntityMatrix(&rsurface.matrix);
Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
- VectorSet(rsurface.glowmod, 1, 1, 1);
+ Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
+ VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
rsurface.frameblend[0].lerp = 1;
rsurface.ent_alttextures = false;
int numtriangles;
// TODO: lock all array ranges before render, rather than on each surface
if (texturenumsurfaces == 1)
- {
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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
int batchtriangles = 0;
- int batchelements[MAXBATCHTRIANGLES*3];
+ static int batchelements[MAXBATCHTRIANGLES*3];
for (i = 0;i < texturenumsurfaces;i = j)
{
surface = texturesurfacelist[i];
surface2 = texturesurfacelist[j-1];
numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
- GL_LockArrays(surface->num_firstvertex, numvertices);
R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
}
}
for (i = 0;i < texturenumsurfaces;i++)
{
surface = texturesurfacelist[i];
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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);
}
}
}
-static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
+static void RSurf_BindLightmapForSurface(const msurface_t *surface)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_CGGL:
+#ifdef SUPPORTCG
+ if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
+#endif
+ break;
+ case RENDERPATH_GL20:
+ if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ R_Mesh_TexBind(0, surface->lightmaptexture);
+ break;
+ }
+}
+
+static void RSurf_BindReflectionForSurface(const msurface_t *surface)
{
- int i, planeindex, vertexindex;
+ // pick the closest matching water plane and bind textures
+ int planeindex, vertexindex;
float d, bestd;
vec3_t vert;
const float *v;
r_waterstate_waterplane_t *p, *bestp;
+ bestd = 0;
+ bestp = NULL;
+ for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
+ {
+ d = 0;
+ for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
+ {
+ Matrix4x4_Transform(&rsurface.matrix, v, vert);
+ d += fabs(PlaneDiff(vert, &p->plane));
+ }
+ if (bestd > d || !bestp)
+ {
+ bestd = d;
+ bestp = p;
+ }
+ }
+ switch(vid.renderpath)
+ {
+ 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
+#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);
+ if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ break;
+ }
+}
+
+static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+{
+ int i;
const msurface_t *surface;
if (r_waterstate.renderingscene)
return;
for (i = 0;i < texturenumsurfaces;i++)
{
surface = texturesurfacelist[i];
- if (lightmaptexunit >= 0)
- R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
- if (deluxemaptexunit >= 0)
- R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
- // pick the closest matching water plane
- bestd = 0;
- bestp = NULL;
- for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
- {
- d = 0;
- for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
- {
- Matrix4x4_Transform(&rsurface.matrix, v, vert);
- d += fabs(PlaneDiff(vert, &p->plane));
- }
- if (bestd > d || !bestp)
- {
- bestd = d;
- bestp = p;
- }
- }
- if (bestp)
- {
- if (refractiontexunit >= 0)
- R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
- if (reflectiontexunit >= 0)
- R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
- }
- else
- {
- if (refractiontexunit >= 0)
- R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
- if (reflectiontexunit >= 0)
- R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
- }
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ RSurf_BindLightmapForSurface(surface);
+ RSurf_BindReflectionForSurface(surface);
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);
}
}
-static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
+static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
int i;
int j;
int endvertex;
int numvertices;
int numtriangles;
- // TODO: lock all array ranges before render, rather than on each surface
if (texturenumsurfaces == 1)
{
- R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
- if (deluxemaptexunit >= 0)
- R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ RSurf_BindLightmapForSurface(surface);
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 4096
int batchtriangles = 0;
- int batchelements[MAXBATCHTRIANGLES*3];
+ static int batchelements[MAXBATCHTRIANGLES*3];
for (i = 0;i < texturenumsurfaces;i = j)
{
surface = texturesurfacelist[i];
- R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
- if (deluxemaptexunit >= 0)
- R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
+ RSurf_BindLightmapForSurface(surface);
j = i + 1;
if (surface->num_triangles > MAXBATCHTRIANGLES)
{
for (i = 0;i < texturenumsurfaces;i = j)
{
surface = texturesurfacelist[i];
- R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
- if (deluxemaptexunit >= 0)
- R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
+ RSurf_BindLightmapForSurface(surface);
for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
break;
surface2 = texturesurfacelist[j-1];
numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
- GL_LockArrays(surface->num_firstvertex, numvertices);
R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
}
#if 0
for (i = 0;i < texturenumsurfaces;i++)
{
surface = texturesurfacelist[i];
- R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
- if (deluxemaptexunit >= 0)
- R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ RSurf_BindLightmapForSurface(surface);
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);
}
}
const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
int k = (int)(((size_t)surface) / sizeof(msurface_t));
GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
- GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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);
}
}
const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
{
- c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
- c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
- c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
+ c2[0] = c[0] + r_refdef.scene.ambient;
+ c2[1] = c[1] + r_refdef.scene.ambient;
+ c2[2] = c[2] + r_refdef.scene.ambient;
c2[3] = c[3];
}
}
if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
}
static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
// transparent sky would be ridiculous
if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
return;
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
skyrenderlater = true;
RSurf_SetupDepthAndCulling();
GL_DepthMask(true);
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
- R_SetupDepthOrShadowShader();
+ R_SetupShader_DepthOrShadow();
// depth-only (masking)
GL_ColorMask(0,0,0,0);
// just to make sure that braindead drivers don't draw
}
else
{
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
}
GL_Color(1, 1, 1, 1);
}
-static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
+extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
+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)))
return;
-
- R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
- R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
- R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
- R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
- R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
- R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
- if (rsurface.texture->backgroundcurrentskinframe)
+ RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
+ if (prepass)
{
- R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
- R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
- R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
- R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
- }
- if(rsurface.texture->colormapping)
- {
- R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
- R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
+ // render screenspace normalmap to texture
+ GL_DepthMask(true);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
- R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
- if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
- R_Mesh_ColorPointer(NULL, 0, 0);
- else
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
-
- if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
+ else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
{
- // render background
- GL_BlendFunc(GL_ONE, GL_ZERO);
+ // render water or distortion background, then blend surface on top
GL_DepthMask(true);
- GL_AlphaTest(false);
-
- GL_Color(1, 1, 1, 1);
- R_Mesh_ColorPointer(NULL, 0, 0);
-
- R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
- if (r_glsl_permutation)
- {
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
- 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);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
- }
- GL_LockArrays(0, 0);
-
- GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ 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);
- if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
- R_Mesh_ColorPointer(NULL, 0, 0);
+ 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
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
- R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
- }
-
- R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
- if (!r_glsl_permutation)
- return;
-
- RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
- 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);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
-
- if (r_glsl_permutation->loc_Texture_Refraction >= 0)
- {
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthMask(true);
- GL_AlphaTest(false);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
else
{
- GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ // render surface normally
GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
- }
-
- if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- {
- if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
- else
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
- }
- else
- {
- if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
+ 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))
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
else
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
- GL_LockArrays(0, 0);
}
static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
int texturesurfaceindex;
qboolean applycolor;
qboolean applyfog;
- rmeshstate_t m;
int layerindex;
const texturelayer_t *layer;
RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
layercolor[3] = layer->color[3];
applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
R_Mesh_ColorPointer(NULL, 0, 0);
- applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
+ applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
case TEXTURELAYERTYPE_LITTEXTURE:
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(r_texture_white);
- m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
- m.tex[1] = R_GetTexture(layer->texture);
- m.texmatrix[1] = layer->texmatrix;
- m.texrgbscale[1] = layertexrgbscale;
- m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ // single-pass lightmapped texture with 2x rgbscale
+ R_Mesh_TexBind(0, r_texture_white);
+ R_Mesh_TexMatrix(0, NULL);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
+ R_Mesh_TexBind(1, layer->texture);
+ R_Mesh_TexMatrix(1, &layer->texmatrix);
+ R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
+ R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else if (rsurface.uselightmaptexture)
RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_TEXTURE:
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.texrgbscale[0] = layertexrgbscale;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ // singletexture unlit texture with transparency support
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ R_Mesh_TexBind(1, 0);
+ R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
- memset(&m, 0, sizeof(m));
- m.texrgbscale[0] = layertexrgbscale;
+ // singletexture fogging
if (layer->texture)
{
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
+ }
+ else
+ {
+ R_Mesh_TexBind(0, 0);
+ R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
}
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(1, 0);
+ R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
// generate a color array for the fog pass
R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
}
- GL_LockArrays(0, 0);
}
CHECKGLERROR
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
// OpenGL 1.1 - crusty old voodoo path
int texturesurfaceindex;
qboolean applyfog;
- rmeshstate_t m;
int layerindex;
const texturelayer_t *layer;
RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
GL_DepthMask(layer->depthmask && writedepth);
GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
R_Mesh_ColorPointer(NULL, 0, 0);
- applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
+ applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
case TEXTURELAYERTYPE_LITTEXTURE:
{
// two-pass lit texture with 2x rgbscale
// first the lightmap pass
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(r_texture_white);
- m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(0, r_texture_white);
+ R_Mesh_TexMatrix(0, NULL);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
else if (rsurface.uselightmaptexture)
RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
else
RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
- GL_LockArrays(0, 0);
// then apply the texture to it
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
}
else
{
// single pass vertex-lighting-only texture with 1x rgbscale and transparency support
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
else
break;
case TEXTURELAYERTYPE_TEXTURE:
// singletexture unlit texture with transparency support
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
// singletexture fogging
- R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
if (layer->texture)
{
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(layer->texture);
- m.texmatrix[0] = layer->texmatrix;
- m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
- m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
- m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
- R_Mesh_TextureState(&m);
+ R_Mesh_TexBind(0, layer->texture);
+ R_Mesh_TexMatrix(0, &layer->texmatrix);
+ R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
+ R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
}
else
- R_Mesh_ResetTextureState();
+ {
+ R_Mesh_TexBind(0, 0);
+ R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
+ }
// generate a color array for the fog pass
+ R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
int i;
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
}
- GL_LockArrays(0, 0);
}
CHECKGLERROR
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
GL_AlphaTest(false);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
if(rsurface.texture && rsurface.texture->currentskinframe)
{
c[3] = 1;
}
- if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
+ if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
{
c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
-static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
+static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3)
+ if (r_showsurfaces.integer == 3 && !prepass)
{
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
return;
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
+ case RENDERPATH_CGGL:
+ R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
break;
case RENDERPATH_GL13:
R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
CHECKGLERROR
}
-static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
+static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3)
+ if (r_showsurfaces.integer == 3 && !prepass)
{
R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
return;
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
+ case RENDERPATH_CGGL:
+ R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
break;
case RENDERPATH_GL13:
R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
int texturenumsurfaces, endsurface;
texture_t *texture;
const msurface_t *surface;
- const msurface_t *texturesurfacelist[1024];
+ const msurface_t *texturesurfacelist[256];
// if the model is static it doesn't matter what value we give for
// wantnormals and wanttangents, so this logic uses only rules applicable
if (ent == r_refdef.scene.worldentity)
RSurf_ActiveWorldEntity();
else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
- RSurf_ActiveModelEntity(ent, false, false);
+ RSurf_ActiveModelEntity(ent, false, false, false);
else
{
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- RSurf_ActiveModelEntity(ent, true, true);
+ case RENDERPATH_CGGL:
+ RSurf_ActiveModelEntity(ent, true, true, false);
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
- RSurf_ActiveModelEntity(ent, true, false);
+ RSurf_ActiveModelEntity(ent, true, false, false);
break;
}
}
+ if (r_transparentdepthmasking.integer)
+ {
+ qboolean setup = false;
+ for (i = 0;i < numsurfaces;i = j)
+ {
+ j = i + 1;
+ surface = rsurface.modelsurfaces + surfacelist[i];
+ texture = surface->texture;
+ rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
+ // scan ahead until we find a different texture
+ endsurface = min(i + 1024, numsurfaces);
+ texturenumsurfaces = 0;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ for (;j < endsurface;j++)
+ {
+ surface = rsurface.modelsurfaces + surfacelist[j];
+ if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ }
+ if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
+ continue;
+ // render the range of surfaces as depth
+ if (!setup)
+ {
+ setup = true;
+ GL_ColorMask(0,0,0,0);
+ GL_Color(1,1,1,1);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_AlphaTest(false);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ResetTextureState();
+ R_SetupShader_DepthOrShadow();
+ }
+ RSurf_SetupDepthAndCulling();
+ RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ }
+ if (setup)
+ GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
+ }
+
for (i = 0;i < numsurfaces;i = j)
{
j = i + 1;
}
// render the range of surfaces
if (ent == r_refdef.scene.worldentity)
- R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
+ R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
else
- R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
+ R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
}
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
GL_AlphaTest(false);
}
-static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
+static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
+{
+ // transparent surfaces get pushed off into the transparent queue
+ int surfacelistindex;
+ const msurface_t *surface;
+ vec3_t tempcenter, center;
+ for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
+ {
+ surface = texturesurfacelist[surfacelistindex];
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
+ if (queueentity->transparent_offset) // transparent offset
+ {
+ center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
+ center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
+ center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
+ }
+ R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
+ }
+}
+
+static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
const entity_render_t *queueentity = r_refdef.scene.worldentity;
CHECKGLERROR
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
- else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
+ else if (prepass)
+ {
+ if (!rsurface.texture->currentnumlayers)
+ return;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ else
+ R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
+ }
+ else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
{
RSurf_SetupDepthAndCulling();
GL_AlphaTest(false);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
GL_DepthMask(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthTest(writedepth);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
- else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
+ else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
{
RSurf_SetupDepthAndCulling();
GL_AlphaTest(false);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
GL_DepthMask(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
return;
else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
{
- // transparent surfaces get pushed off into the transparent queue
- int surfacelistindex;
- const msurface_t *surface;
- vec3_t tempcenter, center;
- for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
- {
- surface = texturesurfacelist[surfacelistindex];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
- Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
- R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
- }
+ // in the deferred case, transparent surfaces were queued during prepass
+ if (!r_shadow_usingdeferredprepass)
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
}
else
{
// the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
- R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
+ R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
}
CHECKGLERROR
}
-void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
+void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
int i, j;
texture_t *texture;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
+ rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
// if this texture is not the kind we want, skip ahead to the next one
for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
;
// render the range of surfaces
- R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
+ R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
}
}
-static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
+static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
{
CHECKGLERROR
if (depthonly)
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
+ else if (prepass)
+ {
+ if (!rsurface.texture->currentnumlayers)
+ return;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
+ else
+ R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
+ }
else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
{
RSurf_SetupDepthAndCulling();
GL_AlphaTest(false);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
GL_DepthMask(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_AlphaTest(false);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
GL_DepthMask(true);
GL_BlendFunc(GL_ONE, GL_ZERO);
return;
else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
{
- // transparent surfaces get pushed off into the transparent queue
- int surfacelistindex;
- const msurface_t *surface;
- vec3_t tempcenter, center;
- for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
- {
- surface = texturesurfacelist[surfacelistindex];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
- Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
- if (queueentity->transparent_offset) // transparent offset
- {
- center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
- center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
- center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
- }
- R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
- }
+ // in the deferred case, transparent surfaces were queued during prepass
+ if (!r_shadow_usingdeferredprepass)
+ R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
}
else
{
// the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
- R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
+ R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
}
CHECKGLERROR
}
-void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
+void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
{
int i, j;
texture_t *texture;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
+ rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
// if this texture is not the kind we want, skip ahead to the next one
for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
;
// render the range of surfaces
- R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
+ R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
}
}
GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
GL_DepthTest(true);
GL_CullFace(GL_NONE);
- R_Mesh_Matrix(&identitymatrix);
+ R_EntityMatrix(&identitymatrix);
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
i = surfacelist[0];
GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
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];
R_DecalSystem_Reset(decalsystem);
decalsystem->model = model;
- RSurf_ActiveModelEntity(ent, false, false);
+ RSurf_ActiveModelEntity(ent, false, false, false);
Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
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)
{
r_decalsystem_splatqueue_t;
int r_decalsystem_numqueued = 0;
-#define MAX_DECALSYSTEM_QUEUE 1024
r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
decalsystem_t *decalsystem = &ent->decalsystem;
int numdecals;
tridecal_t *decal;
- float fadedelay;
float faderate;
float alpha;
float *v3f;
float *c4f;
float *t2f;
const int *e;
- const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
+ const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
int numtris = 0;
numdecals = decalsystem->numdecals;
if (ent == r_refdef.scene.worldentity)
RSurf_ActiveWorldEntity();
else
- RSurf_ActiveModelEntity(ent, false, false);
+ RSurf_ActiveModelEntity(ent, false, false, false);
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
if (!decal->color4ub[0][3])
continue;
- if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
+ if (surfacevisible && !surfacevisible[decal->surfaceindex])
continue;
// update color values for fading decals
if (numtris > 0)
{
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);
R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
- R_SetupGenericShader(true);
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
GL_DepthTest(true);
GL_CullFace(GL_NONE);
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
- //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
- GL_LockArrays(0, numtris * 3);
+ R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
- GL_LockArrays(0, 0);
}
}
R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
- if (!r_drawentities.integer)
- return;
-
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
{
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;
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupGenericShader(false);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_DepthRange(0, 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(false);
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);
extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
int r_maxsurfacelist = 0;
const msurface_t **r_surfacelist = NULL;
-void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
+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;
update = model->brushq1.lightmapupdateflags;
// update light styles on this submodel
- if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
+ if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
model_brush_lightstyleinfo_t *style;
for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
return;
}
- f = 0;
- t = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
r_surfacelist[numsurfacelist++] = surfaces + j;
}
// update lightmaps if needed
- if (update)
+ if (model->brushq1.firstrender)
+ {
+ model->brushq1.firstrender = false;
+ for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
+ if (update[j])
+ R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
+ }
+ else if (update)
+ {
for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
if (r_refdef.viewcache.world_surfacevisible[j])
if (update[j])
R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
+ }
// don't do anything if there were no surfaces
if (!numsurfacelist)
{
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
return;
}
- R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
+ R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
GL_AlphaTest(false);
// add to stats if desired
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
+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;
if (ent == r_refdef.scene.worldentity)
RSurf_ActiveWorldEntity();
else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
- RSurf_ActiveModelEntity(ent, false, false);
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ else if (prepass)
+ RSurf_ActiveModelEntity(ent, true, true, true);
else if (depthonly)
- RSurf_ActiveModelEntity(ent, false, false);
+ RSurf_ActiveModelEntity(ent, false, false, false);
else
{
switch (vid.renderpath)
{
case RENDERPATH_GL20:
- RSurf_ActiveModelEntity(ent, true, true);
+ case RENDERPATH_CGGL:
+ RSurf_ActiveModelEntity(ent, true, true, false);
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
- RSurf_ActiveModelEntity(ent, true, false);
+ RSurf_ActiveModelEntity(ent, true, false, false);
break;
}
}
update = model->brushq1.lightmapupdateflags;
// update light styles
- if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
+ if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
{
model_brush_lightstyleinfo_t *style;
for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
return;
}
- f = 0;
- t = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
return;
}
// update lightmaps if needed
+ if (update)
+ {
+ int updated = 0;
+ for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
+ {
+ if (update[j])
+ {
+ updated++;
+ R_BuildLightMap(ent, surfaces + j);
+ }
+ }
+ }
if (update)
for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
if (update[j])
R_BuildLightMap(ent, surfaces + j);
- R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
+ R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
GL_AlphaTest(false);
// add to stats if desired
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
-void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
+void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
{
static texture_t texture;
static msurface_t surface;
// now render it
rsurface.texture = R_GetCurrentTexture(surface.texture);
rsurface.uselightmaptexture = false;
- R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);
+ R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
+}
+
+void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
+{
+ static msurface_t surface;
+ const msurface_t *surfacelist = &surface;
+
+ // fake enough texture and surface state to render this geometry
+
+ surface.texture = texture;
+ surface.num_triangles = numtriangles;
+ surface.num_firsttriangle = firsttriangle;
+ surface.num_vertices = numvertices;
+ surface.num_firstvertex = firstvertex;
+
+ // now render it
+ rsurface.texture = R_GetCurrentTexture(surface.texture);
+ rsurface.uselightmaptexture = false;
+ R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
}