#include "polygon.h"
#include "image.h"
#include "ft2.h"
+#include "csprogs.h"
+#include "cl_video.h"
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
-static int r_frame = 0; ///< used only by R_GetCurrentTexture
+static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
static qboolean r_loadnormalmap;
static qboolean r_loadgloss;
cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
+cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
+cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
+cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
+cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
+cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
+cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
+
cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
-cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
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_whitecube;
rtexture_t *r_texture_normalizationcube;
rtexture_t *r_texture_fogattenuation;
+rtexture_t *r_texture_fogheighttexture;
rtexture_t *r_texture_gammaramps;
unsigned int r_texture_gammaramps_serial;
//rtexture_t *r_texture_fogintensity;
+rtexture_t *r_texture_reflectcube;
+
+// TODO: hash lookups?
+typedef struct cubemapinfo_s
+{
+ char basename[64];
+ rtexture_t *texture;
+}
+cubemapinfo_t;
+
+int r_texture_numcubemaps;
+cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
unsigned int r_queries[MAX_OCCLUSION_QUERIES];
unsigned int r_numqueries;
0, 1, 0
};
-extern void R_DrawModelShadows(void);
-
void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
{
int i;
r_refdef.fog_end = 16384;
r_refdef.fog_height = 1<<30;
r_refdef.fog_fadedepth = 128;
+ memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
}
static void R_BuildBlankTextures(void)
}
}
+static void R_BuildFogHeightTexture(void)
+{
+ unsigned char *inpixels;
+ int size;
+ int x;
+ int y;
+ int j;
+ float c[4];
+ float f;
+ inpixels = NULL;
+ strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
+ if (r_refdef.fogheighttexturename[0])
+ inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
+ if (!inpixels)
+ {
+ r_refdef.fog_height_tablesize = 0;
+ if (r_texture_fogheighttexture)
+ R_FreeTexture(r_texture_fogheighttexture);
+ r_texture_fogheighttexture = NULL;
+ if (r_refdef.fog_height_table2d)
+ Mem_Free(r_refdef.fog_height_table2d);
+ r_refdef.fog_height_table2d = NULL;
+ if (r_refdef.fog_height_table1d)
+ Mem_Free(r_refdef.fog_height_table1d);
+ r_refdef.fog_height_table1d = NULL;
+ return;
+ }
+ size = image_width;
+ r_refdef.fog_height_tablesize = size;
+ r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
+ r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
+ memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
+ Mem_Free(inpixels);
+ // LordHavoc: now the magic - what is that table2d for? it is a cooked
+ // average fog color table accounting for every fog layer between a point
+ // and the camera. (Note: attenuation is handled separately!)
+ for (y = 0;y < size;y++)
+ {
+ for (x = 0;x < size;x++)
+ {
+ Vector4Clear(c);
+ f = 0;
+ if (x < y)
+ {
+ for (j = x;j <= y;j++)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ else
+ {
+ for (j = x;j >= y;j--)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ f = 1.0f / f;
+ r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
+ }
+ }
+ r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
+}
+
//=======================================================================================================================================================
static const char *builtinshaderstring =
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#define USELIGHTMAP\n"
"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
+"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\n"
" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
" TexCoord1 = gl_MultiTexCoord0.xy;\n"
"#ifdef USEBLOOM\n"
-" TexCoord2 = gl_MultiTexCoord1.xy;\n"
+" TexCoord2 = gl_MultiTexCoord4.xy;\n"
"#endif\n"
"}\n"
"#endif\n"
"#endif\n"
"//uncomment these if you want to use them:\n"
"uniform vec4 UserVec1;\n"
-"// uniform vec4 UserVec2;\n"
+"uniform vec4 UserVec2;\n"
"// uniform vec4 UserVec3;\n"
"// uniform vec4 UserVec4;\n"
"// uniform float ClientTime;\n"
"#ifdef USEPOSTPROCESSING\n"
"// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
"// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
+" float sobel = 1.0;\n"
+" // vec2 ts = textureSize(Texture_First, 0);\n"
+" // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
+" vec2 px = PixelSize;\n"
+" vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
+" vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
+" vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
+" vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
+" vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
+" vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
+" vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
+" vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
+" vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
+" vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
+" vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
+" vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
+" float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
+" float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
+" float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
+" float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
+" float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
+" float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
+" float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
+" float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
+" float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
+" float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
+" float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
+" float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
+" sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
" gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
-" gl_FragColor /= (1 + 5 * UserVec1.y);\n"
+" gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
+" gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
"#endif\n"
"\n"
"#ifdef USESATURATION\n"
" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
" vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
+" //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
" // FIXME temporary hack to detect the case that the reflection\n"
" // gets blackened at edges due to leaving the area that contains actual\n"
"varying vec3 CubeVector;\n"
"#endif\n"
"\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-"varying vec3 LightVector;\n"
-"#endif\n"
-"#if defined(MODE_LIGHTDIRECTION)\n"
+"#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
"varying vec3 LightVector;\n"
"#endif\n"
"\n"
"varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
"#endif\n"
"\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
"varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
"varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
"#endif\n"
"uniform vec4 FogPlane;\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"varying vec3 ShadowMapTC;\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"\n"
"uniform sampler2D Texture_Normal;\n"
"uniform sampler2D Texture_Color;\n"
-"//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"uniform sampler2D Texture_Gloss;\n"
-"//#endif\n"
"#ifdef USEGLOW\n"
"uniform sampler2D Texture_Glow;\n"
"#endif\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
"uniform sampler2D Texture_SecondaryNormal;\n"
"uniform sampler2D Texture_SecondaryColor;\n"
-"//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"uniform sampler2D Texture_SecondaryGloss;\n"
-"//#endif\n"
"#ifdef USEGLOW\n"
"uniform sampler2D Texture_SecondaryGlow;\n"
"#endif\n"
"uniform sampler2D Texture_Shirt;\n"
"#endif\n"
"#ifdef USEFOG\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+"uniform sampler2D Texture_FogHeightTexture;\n"
+"#endif\n"
"uniform sampler2D Texture_FogMask;\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"#endif\n"
"\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform sampler2DRect Texture_ScreenDepth;\n"
-"uniform sampler2DRect Texture_ScreenNormalMap;\n"
+"uniform sampler2D Texture_ScreenDepth;\n"
+"uniform sampler2D Texture_ScreenNormalMap;\n"
"#endif\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform sampler2DRect Texture_ScreenDiffuse;\n"
-"uniform sampler2DRect Texture_ScreenSpecular;\n"
+"uniform sampler2D Texture_ScreenDiffuse;\n"
+"uniform sampler2D Texture_ScreenSpecular;\n"
"#endif\n"
"\n"
"uniform myhalf3 Color_Pants;\n"
"uniform float FogRangeRecip;\n"
"uniform float FogPlaneViewDist;\n"
"uniform float FogHeightFade;\n"
-"float FogVertex(void)\n"
+"vec3 FogVertex(vec3 surfacecolor)\n"
"{\n"
" vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
" float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+" vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
+" fogfrac = fogheightpixel.a;\n"
+" return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
+"# ifdef USEFOGOUTSIDE\n"
+" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"# endif\n"
+" return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
-" return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
"}\n"
"#endif\n"
"\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
"uniform sampler2D Texture_Attenuation;\n"
"uniform samplerCube Texture_Cube;\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"#endif\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
+"# else\n"
+"# ifdef USESHADOWMAPVSDCT\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" vec2 tc;\n"
-" vec2 offset;\n"
-" float ma;\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z) // X\n"
-" {\n"
-" ma = adir.x;\n"
-" tc = dir.zy;\n"
-" offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (adir.y > adir.z) // Y\n"
-" {\n"
-" ma = adir.y;\n"
-" tc = dir.xz;\n"
-" offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-"\n"
-" vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += offset * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
+" vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
+" vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
+" return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
-"# else\n"
+"# else\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
-" float ma = max(max(adir.x, adir.y), adir.z);\n"
-" vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
+" float ma = adir.z;\n"
+" vec4 proj = vec4(dir, 2.5);\n"
+" if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
+" if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
+" vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
+" return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
+"# endif\n"
"# endif\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"vec4 GetShadowMapTCCube(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"# endif\n"
"\n"
"# endif\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
"# 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"
+" vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
+"# if USESHADOWMAPPCF > 1\n"
+" vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
+" vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
+" vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
+" vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
+" vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
+" vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
+" vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
+" vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
+" vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
+" vec4 locols = vec4(group1.ab, group3.ab);\n"
+" vec4 hicols = vec4(group7.rg, group9.rg);\n"
+" locols.yz += group2.ab;\n"
+" hicols.yz += group8.rg;\n"
+" vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
+" vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
+" mix(locols, hicols, offset.y);\n"
+" vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
+" cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
+" f = dot(cols, vec4(1.0/25.0));\n"
+"# else\n"
" vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
" vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
" vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
" vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"# endif\n"
"# else\n"
"# ifdef GL_EXT_gpu_shader4\n"
"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
" f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
"# endif\n"
"# endif\n"
+"# ifdef USESHADOWMAPORTHO\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
" return f;\n"
"}\n"
"# endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
"#endif // FRAGMENT_SHADER\n"
"\n"
"\n"
"\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
" vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
+" float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
"#else\n"
" vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
+" float a = texture2D(Texture_Gloss, TexCoord).a;\n"
"#endif\n"
"\n"
-" gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
+" gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#else // !MODE_DEFERREDGEOMETRY\n"
"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 / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\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 = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\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"
" // calculate directional shading\n"
" vec3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
"# else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
"# endif\n"
"#endif\n"
"\n"
"\n"
"# ifdef USECUBEFILTER\n"
" vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
-" gl_FragData[0] *= cubecolor;\n"
-" gl_FragData[1] *= cubecolor;\n"
+" gl_FragData[0].rgb *= cubecolor;\n"
+" gl_FragData[1].rgb *= cubecolor;\n"
"# endif\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"#ifdef MODE_LIGHTSOURCE\n"
"uniform mat4 ModelToLight;\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform mat4 ShadowMapMatrix;\n"
+"#endif\n"
"void main(void)\n"
"{\n"
"#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
" EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
"#endif\n"
"\n"
-"#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
" VectorS = gl_MultiTexCoord1.xyz;\n"
" VectorT = gl_MultiTexCoord2.xyz;\n"
" VectorR = gl_MultiTexCoord3.xyz;\n"
" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
" gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
+"#endif\n"
+"\n"
"#ifdef USEREFLECTION\n"
" ModelViewProjectionPosition = gl_Position;\n"
"#endif\n"
"\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 vec4 ScreenCenterRefractReflect;\n"
"uniform myhalf4 ReflectColor;\n"
"#endif\n"
+"#ifdef USEREFLECTCUBE\n"
+"uniform mat4 ModelToReflectCube;\n"
+"uniform sampler2D Texture_ReflectMask;\n"
+"uniform samplerCube Texture_ReflectCube;\n"
+"#endif\n"
"#ifdef MODE_LIGHTDIRECTION\n"
"uniform myhalf3 LightColor;\n"
"#endif\n"
" myhalf3 diffusetex = color.rgb;\n"
"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
+" myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
"# else\n"
-" myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
+" myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USEREFLECTCUBE\n"
+" vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
+" vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
+" vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
+" diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"#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);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"#else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
+"#endif\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
-" color.rgb += glosstex * (specular * Color_Specular);\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"
"\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"
" myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"# else\n"
" myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
-" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"# endif\n"
-" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
+" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"# endif\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
+"#endif\n"
+"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
-" color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
-" color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\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"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= myhalf(FogVertex());\n"
-"#else\n"
-" color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
+"#if defined(USEREFLECTION)\n"
+"#undef USESHADOWMAPORTHO\n"
+"#endif\n"
+"\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#define USELIGHTMAP\n"
"#endif\n"
-"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
+"#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
+"#endif\n"
+"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
"#ifdef VERTEX_SHADER\n"
"void main\n"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix,\n"
"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
+"float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
"out float4 gl_Position : POSITION,\n"
"out float2 TexCoord1 : TEXCOORD0,\n"
"out float2 TexCoord2 : TEXCOORD1\n"
" gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
"#endif\n"
"#ifdef USEVIEWTINT\n"
-" gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
+" gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
"#endif\n"
"\n"
"#ifdef USEPOSTPROCESSING\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 = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
+" gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
"#endif\n"
"\n"
"#ifdef USEGAMMARAMPS\n"
" gl_FragColor += tex2;\n"
"# endif\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
+" gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
"# endif\n"
"#endif\n"
"}\n"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix,\n"
"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
"uniform float3 EyePosition,\n"
"out float4 gl_Position : POSITION,\n"
"out float2 TexCoord : TEXCOORD0,\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 = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
+" ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
" gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
"}\n"
"#endif\n"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix,\n"
"float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
"uniform float3 EyePosition,\n"
"out float4 gl_Position : POSITION,\n"
"out float2 TexCoord : TEXCOORD0,\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 = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\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 = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\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"
"#ifdef FRAGMENT_SHADER\n"
"\n"
"#ifdef USEFOG\n"
-"float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
+"float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
"{\n"
" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+" float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
+" fogfrac = fogheightpixel.a;\n"
+" return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
+"# ifdef USEFOGOUTSIDE\n"
+" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"# endif\n"
+" return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
-" return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
"}\n"
"#endif\n"
"\n"
"}\n"
"#endif // USEOFFSETMAPPING\n"
"\n"
-"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"# ifndef USESHADOWMAPVSDCT\n"
-"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
-"{\n"
-" float3 adir = abs(dir);\n"
-" float2 tc;\n"
-" float2 offset;\n"
-" float ma;\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z) // X\n"
-" {\n"
-" ma = adir.x;\n"
-" tc = dir.zy;\n"
-" offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (adir.y > adir.z) // Y\n"
-" {\n"
-" ma = adir.y;\n"
-" tc = dir.xz;\n"
-" offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-"\n"
-" float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += offset * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
-"}\n"
+"# ifdef USESHADOWMAPORTHO\n"
+"# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
"# else\n"
+"# ifdef USESHADOWMAPVSDCT\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
"{\n"
" float3 adir = abs(dir);\n"
+" float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-" float ma = max(max(adir.x, adir.y), adir.z);\n"
-" float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
+" return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+"}\n"
+"# else\n"
+"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
+"{\n"
+" float3 adir = abs(dir);\n"
+" float ma = adir.z;\n"
+" float4 proj = float4(dir, 2.5);\n"
+" if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
+" if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
+" float2 aparams = ShadowMap_Parameters.xy / ma;\n"
+" return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
+"# endif\n"
"# endif\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"# 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 = fract(center);\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 + mix(row1, row4, offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.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 = fract(shadowmaptc.xy);\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 + mix(row1, row3, offset.y);\n"
-" f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\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"
+"# ifdef USESHADOWMAPORTHO\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
"# else\n"
"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
"# endif\n"
-" float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\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"
-" mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\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"
-"# ifdef GL_EXT_gpu_shader4\n"
-"# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
-"# else\n"
-"# define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
-"# endif\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 = fract(center);\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 + mix(row1, row4, offset.y);\n"
-" f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.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 = fract(shadowmaptc.xy);\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 + mix(row1, row3, offset.y);\n"
-" f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\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"
+"# ifdef USESHADOWMAPORTHO\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
+"# else\n"
+" return f;\n"
+"# endif\n"
"}\n"
"# endif\n"
"\n"
"float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
"float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
"float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix,\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
+"#endif\n"
+"uniform float4x4 ModelViewMatrix,\n"
+"#ifdef USEOFFSETMAPPING\n"
+"uniform float3 EyePosition,\n"
"#endif\n"
-"uniform mat4 ModelViewMatrix,\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"
"#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"
"\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-" float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\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"
"float4 gl_Vertex : POSITION,\n"
"uniform float4x4 ModelViewProjectionMatrix,\n"
-"uniform mat4 ModelViewMatrix,\n"
+"uniform float4x4 ModelViewMatrix,\n"
"out float4 gl_Position : POSITION,\n"
"out float4 ModelViewPosition : TEXCOORD0\n"
")\n"
"(\n"
"float2 Pixel : WPOS,\n"
"float4 ModelViewPosition : TEXCOORD0,\n"
-"uniform mat4 ViewToLight,\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 half SpecularPower,\n"
"#endif\n"
"uniform sampler2D Texture_Attenuation,\n"
-"uniform samplerRECT Texture_ScreenDepth,\n"
-"uniform samplerRECT Texture_ScreenNormalMap,\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
+"\n"
+"#ifdef USECUBEFILTER\n"
+"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
")\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 / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\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 = texRECT(Texture_ScreenNormalMap, Pixel);\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"
" // calculate directional shading\n"
" float3 eyevector = position * -1.0;\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
"# else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
"# endif\n"
"#endif\n"
"\n"
"\n"
"# ifdef USECUBEFILTER\n"
" float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
-" gl_FragData0 *= cubecolor;\n"
-" gl_FragData1 *= cubecolor;\n"
+" gl_FragData0.rgb *= cubecolor;\n"
+" gl_FragData1.rgb *= cubecolor;\n"
"# endif\n"
"}\n"
"#endif // FRAGMENT_SHADER\n"
"float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
"\n"
"uniform float3 EyePosition,\n"
-"uniform mat4 TexMatrix,\n"
+"uniform float4x4 TexMatrix,\n"
"#ifdef USEVERTEXTEXTUREBLEND\n"
-"uniform mat4 BackgroundTexMatrix,\n"
+"uniform float4x4 BackgroundTexMatrix,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
-"uniform mat4 ModelToLight,\n"
+"uniform float4x4 ModelToLight,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
"uniform float3 LightPosition,\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
"uniform float3 LightPosition,\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"uniform float4x4 ShadowMapMatrix,\n"
+"#endif\n"
"\n"
"out float4 gl_FrontColor : COLOR,\n"
"out float4 TexCoordBoth : TEXCOORD0,\n"
"out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
-"out float3 LightVector : TEXCOORD5,\n"
+"out float3 LightVector : TEXCOORD1,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
"out float3 CubeVector : TEXCOORD3,\n"
"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
"out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
+"#endif\n"
"out float4 gl_Position : POSITION\n"
")\n"
"{\n"
" // transform vertex to camera space, using ftransform to match non-VS rendering\n"
" gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
+"#endif\n"
+"\n"
"#ifdef USEREFLECTION\n"
" ModelViewProjectionPosition = gl_Position;\n"
"#endif\n"
"float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
-"float3 LightVector : TEXCOORD5,\n"
+"float3 LightVector : TEXCOORD1,\n"
"#endif\n"
"#ifdef MODE_LIGHTSOURCE\n"
"float3 CubeVector : TEXCOORD3,\n"
"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
"float4 ModelViewPosition : TEXCOORD0,\n"
"#endif\n"
-"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
+"#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
"float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
"float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
+"#ifdef USESHADOWMAPORTHO\n"
+"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
+"#endif\n"
"\n"
"uniform sampler2D Texture_Normal,\n"
"uniform sampler2D Texture_Color,\n"
"uniform sampler2D Texture_Shirt,\n"
"#endif\n"
"#ifdef USEFOG\n"
+"uniform sampler2D Texture_FogHeightTexture,\n"
"uniform sampler2D Texture_FogMask,\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"uniform sampler2D Texture_Reflection,\n"
"#endif\n"
"\n"
-"//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
-"uniform samplerRECT Texture_ScreenDepth,\n"
-"uniform samplerRECT Texture_ScreenNormalMap,\n"
-"//#endif\n"
+"#ifdef MODE_DEFERREDLIGHTSOURCE\n"
+"uniform sampler2D Texture_ScreenDepth,\n"
+"uniform sampler2D Texture_ScreenNormalMap,\n"
+"#endif\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
-"uniform samplerRECT Texture_ScreenDiffuse,\n"
-"uniform samplerRECT Texture_ScreenSpecular,\n"
+"uniform sampler2D Texture_ScreenDiffuse,\n"
+"uniform sampler2D Texture_ScreenSpecular,\n"
"#endif\n"
"\n"
"#ifdef USECOLORMAPPING\n"
"#endif\n"
"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
+"uniform half2 PixelToScreenTexCoord,\n"
"uniform half3 DeferredMod_Diffuse,\n"
"uniform half3 DeferredMod_Specular,\n"
"#endif\n"
"uniform float4 ScreenCenterRefractReflect,\n"
"uniform half4 ReflectColor,\n"
"#endif\n"
+"#ifdef USEREFLECTCUBE\n"
+"uniform float4x4 ModelToReflectCube,\n"
+"uniform sampler2D Texture_ReflectMask,\n"
+"uniform samplerCUBE Texture_ReflectCube,\n"
+"#endif\n"
"#ifdef MODE_LIGHTDIRECTION\n"
"uniform half3 LightColor,\n"
"#endif\n"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
"uniform sampler2D Texture_Attenuation,\n"
"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
+"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"uniform float2 ShadowMap_TextureScale,\n"
"uniform float4 ShadowMap_Parameters,\n"
"#endif\n"
-"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
+"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
"\n"
"out float4 gl_FragColor : COLOR\n"
")\n"
" 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(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
+" color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
" color.a = 1.0;\n"
-" //color = mix(half4(1, 0, 0, 1), color, terrainblend);\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(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\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"
" half3 diffusetex = color.rgb;\n"
"#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
+" half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
"# else\n"
-" half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
+" half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USEREFLECTCUBE\n"
+" float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
+" float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
+" float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
+" diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
"#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);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"#else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
+"#endif\n"
+" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
-" color.rgb += glosstex * (specular * Color_Specular);\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"
"\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"
" half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
"# ifdef USESPECULAR\n"
"# ifdef USEEXACTSPECULARMATH\n"
-" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
"# else\n"
" half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
-" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
+" half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
"# endif\n"
-" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
+" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"# endif\n"
"# endif\n"
"#endif\n"
"\n"
+"#ifdef USESHADOWMAPORTHO\n"
+" color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
+"# if defined(USESHADOWMAP2D)\n"
+"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
+"# endif\n"
+"# if defined(USESHADOWMAPRECT)\n"
+"Texture_ShadowMapRect, ShadowMap_Parameters\n"
+"# endif\n"
+" );\n"
+"#endif\n"
+"\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
-" color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
-" color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
-" color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\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 += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\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());\n"
-"#else\n"
-" color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
" 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 = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
-" color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\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 = float4(color);\n"
"#endif // !MODE_DEPTH_OR_SHADOW\n"
;
+char *glslshaderstring = NULL;
+char *cgshaderstring = NULL;
+
//=======================================================================================================================================================
typedef struct shaderpermutationinfo_s
SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
- SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
- SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
- SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
+ SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
+ SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
+ SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+ SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+ SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESATURATION\n", " saturation"},
{"#define USEFOGINSIDE\n", " foginside"},
{"#define USEFOGOUTSIDE\n", " fogoutside"},
+ {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
{"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
{"#define USESHADOWSAMPLER\n", " shadowsampler"},
{"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
+ {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
{"#define USEALPHAKILL\n", " alphakill"},
+ {"#define USEREFLECTCUBE\n", " reflectcube"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
{
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
- {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
+ {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
{"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
int loc_Texture_SecondaryGlow;
int loc_Texture_Pants;
int loc_Texture_Shirt;
+ int loc_Texture_FogHeightTexture;
int loc_Texture_FogMask;
int loc_Texture_Lightmap;
int loc_Texture_Deluxemap;
int loc_Texture_ScreenNormalMap;
int loc_Texture_ScreenDiffuse;
int loc_Texture_ScreenSpecular;
+ int loc_Texture_ReflectMask;
+ int loc_Texture_ReflectCube;
int loc_Alpha;
int loc_BloomBlur_Parameters;
int loc_ClientTime;
int loc_BackgroundTexMatrix;
int loc_ModelViewProjectionMatrix;
int loc_ModelViewMatrix;
+ int loc_PixelToScreenTexCoord;
+ int loc_ModelToReflectCube;
+ int loc_ShadowMapMatrix;
}
r_glsl_permutation_t;
char *shaderstring;
if (!filename || !filename[0])
return NULL;
+ if (!strcmp(filename, "glsl/default.glsl"))
+ {
+ if (!glslshaderstring)
+ {
+ glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+ if (glslshaderstring)
+ Con_DPrintf("Loading shaders from file %s...\n", filename);
+ else
+ glslshaderstring = (char *)builtinshaderstring;
+ }
+ shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
+ memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
+ return shaderstring;
+ }
shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
if (shaderstring)
{
Con_DPrintf("from disk %s... ", filename);
return shaderstring;
}
- else if (!strcmp(filename, "glsl/default.glsl"))
- {
- shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
- memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
- }
return shaderstring;
}
p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
+ p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
+ p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
p->loc_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");
+ p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
// initialize the samplers to refer to the texture units we use
if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
+ if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
- if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
+ if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
- if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
+ if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
+ if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
+ if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
CHECKGLERROR
Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
}
}
if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
+ if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
}
#ifdef SUPPORTCG
CGparameter vp_BackgroundTexMatrix;
CGparameter vp_ModelViewProjectionMatrix;
CGparameter vp_ModelViewMatrix;
+ CGparameter vp_ShadowMapMatrix;
CGparameter fp_Texture_First;
CGparameter fp_Texture_Second;
CGparameter fp_Texture_SecondaryGlow;
CGparameter fp_Texture_Pants;
CGparameter fp_Texture_Shirt;
+ CGparameter fp_Texture_FogHeightTexture;
CGparameter fp_Texture_FogMask;
CGparameter fp_Texture_Lightmap;
CGparameter fp_Texture_Deluxemap;
CGparameter fp_Texture_ScreenNormalMap;
CGparameter fp_Texture_ScreenDiffuse;
CGparameter fp_Texture_ScreenSpecular;
+ CGparameter fp_Texture_ReflectMask;
+ CGparameter fp_Texture_ReflectCube;
CGparameter fp_Alpha;
CGparameter fp_BloomBlur_Parameters;
CGparameter fp_ClientTime;
CGparameter fp_UserVec4;
CGparameter fp_ViewTintColor;
CGparameter fp_ViewToLight;
+ CGparameter fp_PixelToScreenTexCoord;
+ CGparameter fp_ModelToReflectCube;
}
r_cg_permutation_t;
char *shaderstring;
if (!filename || !filename[0])
return NULL;
+ if (!strcmp(filename, "cg/default.cg"))
+ {
+ if (!cgshaderstring)
+ {
+ cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
+ if (cgshaderstring)
+ Con_DPrintf("Loading shaders from file %s...\n", filename);
+ else
+ cgshaderstring = (char *)builtincgshaderstring;
+ }
+ shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
+ memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
+ return shaderstring;
+ }
shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
if (shaderstring)
{
Con_DPrintf("from disk %s... ", filename);
return shaderstring;
}
- else if (!strcmp(filename, "cg/default.cg"))
- {
- shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
- memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
- }
return shaderstring;
}
+static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
+{
+ // TODO: load or create .fp and .vp shader files
+}
+
static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
{
int i;
const char *geomstrings_list[32+3];
const char *fragstrings_list[32+3];
char permutationname[256];
+ char cachename[256];
CGprofile vertexProfile;
CGprofile fragmentProfile;
p->fprogram = NULL;
permutationname[0] = 0;
+ cachename[0] = 0;
vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
+ strlcat(cachename, "cg/", sizeof(cachename));
// the first pretext is which type of shader to compile as
// (later these will all be bound together as a program object)
geomstrings_list[geomstrings_count++] = modeinfo->pretext;
fragstrings_list[fragstrings_count++] = modeinfo->pretext;
strlcat(permutationname, modeinfo->name, sizeof(permutationname));
+ strlcat(cachename, modeinfo->name, sizeof(cachename));
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
+ strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
}
else
{
}
}
+ // replace spaces in the cachename with _ characters
+ for (i = 0;cachename[i];i++)
+ if (cachename[i] == ' ')
+ cachename[i] = '_';
+
// now append the shader text itself
vertstrings_list[vertstrings_count++] = vertexstring;
geomstrings_list[geomstrings_count++] = geometrystring;
//cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
CHECKGLERROR
- // compile the vertex program
- if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
+ // try to load the cached shader, or generate one
+ R_CG_CacheShader(p, cachename, vertstring, fragstring);
+
+ // if caching failed, do a dynamic compile for now
+ CHECKCGERROR
+ if (vertstring[0] && !p->vprogram)
+ p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
+ CHECKCGERROR
+ if (fragstring[0] && !p->fprogram)
+ p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
+ CHECKCGERROR
+
+ // look up all the uniform variable names we care about, so we don't
+ // have to look them up every time we set them
+ if (p->vprogram)
{
CHECKCGERROR
- cgCompileProgram(p->vprogram);CHECKCGERROR
- if (!cgIsProgramCompiled(p->vprogram))
- {
- CHECKCGERROR
- cgDestroyProgram(p->vprogram);CHECKCGERROR
- p->vprogram = 0;
- }
- else
- {
- cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
- cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
- // look up all the uniform variable names we care about, so we don't
- // have to look them up every time we set them
- CHECKCGERROR
- p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
- p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
- p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
- p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
- p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
- p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
- p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
- p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
- p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
- CHECKCGERROR
- }
+ cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
+ p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
+ p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
+ p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
+ p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
+ p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
+ p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
+ p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
+ p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
+ p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
+ p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
+ CHECKCGERROR
}
-
- // compile the fragment program
- if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
+ if (p->fprogram)
{
- cgCompileProgram(p->fprogram);CHECKCGERROR
- if (!cgIsProgramCompiled(p->fprogram))
- {
- CHECKCGERROR
- cgDestroyProgram(p->fprogram);CHECKCGERROR
- p->fprogram = 0;
- }
- else
- {
- cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
- cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
- CHECKCGERROR
- p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
- p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
- p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
- p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
- p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
- p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
- p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
- p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
- p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
- p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
- p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
- p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
- p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
- p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
- p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
- p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
- p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
- p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
- p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
- p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
- p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
- p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
- p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
- p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
- p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
- p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
- p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
- p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
- p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
- p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
- p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
- p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
- p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
- p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
- p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
- p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
- p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
- p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
- p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
- p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
- p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
- p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
- p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
- p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
- p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
- p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
- p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
- p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
- p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
- p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
- p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
- p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
- p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
- p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
- p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
- p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
- p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
- p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
- p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
- p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
- p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
- p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
- p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
- p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
- p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
- p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
- p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
- p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
- p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
- p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
- p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
- CHECKCGERROR
- }
+ CHECKCGERROR
+ cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
+ p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
+ p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
+ p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
+ p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
+ p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
+ p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
+ p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
+ p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
+ p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
+ p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
+ p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
+ p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
+ p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
+ p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
+ p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
+ p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
+ p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
+ p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
+ p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
+ p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
+ p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
+ p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
+ p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
+ p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
+ p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
+ p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
+ p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
+ p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
+ p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
+ p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
+ p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
+ p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
+ p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
+ p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
+ p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
+ p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
+ p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
+ p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
+ p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
+ p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
+ p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
+ p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
+ p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
+ p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
+ p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
+ p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
+ p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
+ p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
+ p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
+ p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
+ p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
+ p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
+ p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
+ p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
+ p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
+ p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
+ p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
+ p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
+ p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
+ p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
+ p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
+ p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
+ p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
+ p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
+ p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
+ p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
+ p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
+ p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
+ p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
+ p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
+ p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
+ p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
+ p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
+ p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
+ p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
+ p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
+ CHECKCGERROR
}
if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
CHECKCGERROR
if (r_cg_permutation->vprogram)
{
- //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
+ cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
- //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
}
else
{
- //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
+ cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
}
if (r_cg_permutation->fprogram)
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, int texnum)
+void CG_BindTexture(CGparameter param, rtexture_t *tex)
{
- cgGLSetTextureParameter(param, texnum);
+ cgGLSetTextureParameter(param, R_GetTexture(tex));
cgGLEnableTextureParameter(param);
}
#endif
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_glsl_permutation_t *p;
+ r_glsl_permutation = NULL;
limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
for (i = 0;i < limit;i++)
{
#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++)
{
Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
}
}
+ memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
}
- memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
break;
#endif
case RENDERPATH_GL13:
extern qboolean r_shadow_usingshadowmaprect;
extern qboolean r_shadow_usingshadowmapcube;
extern qboolean r_shadow_usingshadowmap2d;
+extern qboolean r_shadow_usingshadowmaportho;
extern float r_shadow_shadowmap_texturescale[2];
extern float r_shadow_shadowmap_parameters[4];
extern qboolean r_shadow_shadowmapvsdct;
extern rtexture_t *r_shadow_shadowmap2dtexture;
extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
extern rtexture_t *r_shadow_shadowmapvsdcttexture;
+extern matrix4x4_t r_shadow_shadowmapmatrix;
extern int r_shadow_shadowmaplod; // changes for each light based on distance
extern int r_shadow_prepass_width;
extern int r_shadow_prepass_height;
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)
+extern cvar_t gl_mesh_separatearrays;
+void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
// select a permutation of the lighting shader appropriate to this
// combination of texture, entity, light source, and fogging, only use the
unsigned int permutation = 0;
unsigned int mode = 0;
float m16f[16];
- // 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;
- }
if (rsurfacepass == RSURFPASS_BACKGROUND)
{
// distorted background
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
mode = SHADERMODE_WATER;
- else
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
mode = SHADERMODE_REFRACTION;
+ else
+ {
+ mode = SHADERMODE_GENERIC;
+ permutation |= SHADERPERMUTATION_DIFFUSE;
+ }
+ GL_AlphaTest(false);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
{
+ if (r_glsl_offsetmapping.integer)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ if (rsurface.texture->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;
- if (r_glsl_offsetmapping.integer)
- {
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
- }
+ GL_AlphaTest(false);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
+ if (r_glsl_offsetmapping.integer)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
// 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;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
else if (r_shadow_shadowmappcf)
permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
}
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
+ if (r_glsl_offsetmapping.integer)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
// unshaded geometry (fullbright or ambient model lighting)
mode = SHADERMODE_FLATCOLOR;
ambientscale = diffusescale = specularscale = 0;
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
- permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_glsl_offsetmapping.integer)
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
+ 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)
{
- // directional model lighting
- mode = SHADERMODE_LIGHTDIRECTION;
+ if (r_glsl_offsetmapping.integer)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ // 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;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+ {
+ permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
+ 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)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
+ // 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 |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+ {
+ permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
permutation |= SHADERPERMUTATION_REFLECTION;
if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
+ 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)
+ {
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
+ permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
// lightmapped wall
+ if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
+ permutation |= SHADERPERMUTATION_GLOW;
+ if (r_refdef.fogenabled)
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
+ if (rsurface.texture->colormapping)
+ permutation |= SHADERPERMUTATION_COLORMAPPING;
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
+ {
+ permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+
+ if (r_shadow_shadowmapsampler)
+ permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
+ if (r_shadow_shadowmappcf > 1)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
+ else if (r_shadow_shadowmappcf)
+ permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+ }
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
+ permutation |= SHADERPERMUTATION_REFLECTION;
+ if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
+ permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
+ if (rsurface.texture->reflectmasktexture)
+ permutation |= SHADERPERMUTATION_REFLECTCUBE;
if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
{
// deluxemapping (light direction texture)
mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
permutation |= SHADERPERMUTATION_DIFFUSE;
if (specularscale > 0)
+ {
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
+ if (r_shadow_glossexact.integer)
+ permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
+ }
}
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;
+ }
}
else if (rsurface.uselightmaptexture)
{
// ordinary vertex coloring (q3bsp)
mode = SHADERMODE_VERTEXCOLOR;
}
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
- permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
- permutation |= SHADERPERMUTATION_GLOW;
- if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
- 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;
+ GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
- if(permutation & SHADERPERMUTATION_SPECULAR)
- if(r_shadow_glossexact.integer)
- permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
- if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
- permutation |= SHADERPERMUTATION_ALPHAKILL;
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ if (gl_mesh_separatearrays.integer)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
+ R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
+ }
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_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, specularscale, specularscale, specularscale);
+ 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
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, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
- if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
+ 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_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 * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
+ 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);
}
}
if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
+ if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
+ if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+ if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
+
if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
- if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
+ if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
+ if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
// if (r_glsl_permutation->loc_Texture_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_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
+ if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
+ if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
+ if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , 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_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
- if (rsurface.rtlight)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
- if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
- if (r_shadow_usingshadowmapcube)
- if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
- if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
+ if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
+ if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
+ if (rsurface.rtlight)
+ {
+ if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
+ if (r_shadow_usingshadowmapcube)
+ if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
+ if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
+ }
}
CHECKGLERROR
break;
case RENDERPATH_CGGL:
#ifdef SUPPORTCG
+ if (gl_mesh_separatearrays.integer)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
+ R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
+ R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
+ R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
+ }
R_SetupShader_SetPermutationCG(mode, permutation);
+ if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
if (mode == SHADERMODE_LIGHTSOURCE)
{
if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
}
if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
+ if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
CHECKGLERROR
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, specularscale, specularscale, specularscale);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
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, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
- if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);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_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 * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);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
}
if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
}
+ if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
+ if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
if (r_cg_permutation->fp_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_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ReflectCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
- if (rsurface.rtlight)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
- if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
- if (r_shadow_usingshadowmapcube)
- if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
- if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
+ if (rsurface.rtlight)
+ {
+ if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
+ if (r_shadow_usingshadowmapcube)
+ if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
+ }
}
CHECKGLERROR
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_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
R_PurgeTexture(s->gloss );s->gloss = NULL;
R_PurgeTexture(s->glow );s->glow = NULL;
R_PurgeTexture(s->fog );s->fog = NULL;
+ R_PurgeTexture(s->reflect);s->reflect = NULL;
s->loadsequence = 0;
}
}
// check for DDS texture file first
if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
{
- basepixels = loadimagepixelsbgra(name, complain, true);
+ basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
if (basepixels == NULL)
return NULL;
}
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
if (ddsbase)
skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
+ skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
}
// _norm is the name used by tenebrae and has been adopted as standard
if (r_loadnormalmap && skinframe->nmap == NULL)
{
- if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
+ if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
{
skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
Mem_Free(pixels);
pixels = NULL;
}
- else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
+ else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
// _luma is supported only for tenebrae compatibility
// _glow is the preferred name
- if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
+ if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
{
skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
Mem_Free(pixels);pixels = NULL;
}
- if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
+ if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
pixels = NULL;
}
- if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
+ if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
pixels = NULL;
}
- if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
+ if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
{
skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
pixels = NULL;
}
+ if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ {
+ skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
+ R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
+ Mem_Free(pixels);
+ pixels = NULL;
+ }
+
if (basepixels)
Mem_Free(basepixels);
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
// if no data was provided, then clearly the caller wanted to get a blank skinframe
skinframe->gloss = NULL;
skinframe->glow = NULL;
skinframe->fog = NULL;
+ skinframe->reflect = NULL;
skinframe->hasalpha = false;
skinframe->avgcolor[0] = rand() / RAND_MAX;
return skinframe;
}
+//static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
+typedef struct suffixinfo_s
+{
+ char *suffix;
+ qboolean flipx, flipy, flipdiagonal;
+}
+suffixinfo_t;
+static suffixinfo_t suffix[3][6] =
+{
+ {
+ {"px", false, false, false},
+ {"nx", false, false, false},
+ {"py", false, false, false},
+ {"ny", false, false, false},
+ {"pz", false, false, false},
+ {"nz", false, false, false}
+ },
+ {
+ {"posx", false, false, false},
+ {"negx", false, false, false},
+ {"posy", false, false, false},
+ {"negy", false, false, false},
+ {"posz", false, false, false},
+ {"negz", false, false, false}
+ },
+ {
+ {"rt", true, false, true},
+ {"lf", false, true, true},
+ {"ft", true, true, false},
+ {"bk", false, false, false},
+ {"up", true, false, true},
+ {"dn", true, false, true}
+ }
+};
+
+static int componentorder[4] = {0, 1, 2, 3};
+
+rtexture_t *R_LoadCubemap(const char *basename)
+{
+ int i, j, cubemapsize;
+ unsigned char *cubemappixels, *image_buffer;
+ rtexture_t *cubemaptexture;
+ char name[256];
+ // must start 0 so the first loadimagepixels has no requested width/height
+ cubemapsize = 0;
+ cubemappixels = NULL;
+ cubemaptexture = NULL;
+ // keep trying different suffix groups (posx, px, rt) until one loads
+ for (j = 0;j < 3 && !cubemappixels;j++)
+ {
+ // load the 6 images in the suffix group
+ for (i = 0;i < 6;i++)
+ {
+ // generate an image name based on the base and and suffix
+ dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+ // load it
+ if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
+ {
+ // an image loaded, make sure width and height are equal
+ if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
+ {
+ // if this is the first image to load successfully, allocate the cubemap memory
+ if (!cubemappixels && image_width >= 1)
+ {
+ cubemapsize = image_width;
+ // note this clears to black, so unavailable sides are black
+ cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
+ }
+ // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
+ if (cubemappixels)
+ Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
+ }
+ else
+ Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
+ // free the image
+ Mem_Free(image_buffer);
+ }
+ }
+ }
+ // if a cubemap loaded, upload it
+ if (cubemappixels)
+ {
+ if (developer_loading.integer)
+ Con_Printf("loading cubemap \"%s\"\n", basename);
+
+ cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
+ Mem_Free(cubemappixels);
+ }
+ else
+ {
+ Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
+ if (developer_loading.integer)
+ {
+ Con_Printf("(tried tried images ");
+ for (j = 0;j < 3;j++)
+ for (i = 0;i < 6;i++)
+ Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
+ Con_Print(" and was unable to find any of them).\n");
+ }
+ }
+ return cubemaptexture;
+}
+
+rtexture_t *R_GetCubemap(const char *basename)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
+ return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
+ if (i >= MAX_CUBEMAPS)
+ return r_texture_whitecube;
+ r_texture_numcubemaps++;
+ strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
+ r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
+ return r_texture_cubemaps[i].texture;
+}
+
+void R_FreeCubemaps(void)
+{
+ int i;
+ for (i = 0;i < r_texture_numcubemaps;i++)
+ {
+ if (developer_loading.integer)
+ Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
+ if (r_texture_cubemaps[i].texture)
+ R_FreeTexture(r_texture_cubemaps[i].texture);
+ }
+ r_texture_numcubemaps = 0;
+}
+
void R_Main_FreeViewCache(void)
{
if (r_refdef.viewcache.entityvisible)
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
+ r_texture_numcubemaps = 0;
r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
R_BuildNormalizationCube();
}
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
+ r_glsl_permutation = NULL;
memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
+ glslshaderstring = NULL;
#ifdef SUPPORTCG
+ r_cg_permutation = NULL;
memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
+ cgshaderstring = NULL;
#endif
memset(&r_svbsp, 0, sizeof (r_svbsp));
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
+ r_texture_numcubemaps = 0;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
memset(&r_waterstate, 0, sizeof(r_waterstate));
+ r_glsl_permutation = NULL;
+ memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
+ glslshaderstring = NULL;
+#ifdef SUPPORTCG
+ r_cg_permutation = NULL;
+ memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
+ cgshaderstring = NULL;
+#endif
R_GLSL_Restart_f();
}
void gl_main_newmap(void)
{
// FIXME: move this code to client
- int l;
char *entities, entname[MAX_QPATH];
if (r_qwskincache)
Mem_Free(r_qwskincache);
r_qwskincache_size = 0;
if (cl.worldmodel)
{
- strlcpy(entname, cl.worldmodel->name, sizeof(entname));
- l = (int)strlen(entname) - 4;
- if (l >= 0 && !strcmp(entname + l, ".bsp"))
+ dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
+ if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
{
- memcpy(entname + l, ".ent", 5);
- if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
- {
- CL_ParseEntityLump(entities);
- Mem_Free(entities);
- return;
- }
+ CL_ParseEntityLump(entities);
+ Mem_Free(entities);
+ return;
}
if (cl.worldmodel->brush.entities)
CL_ParseEntityLump(cl.worldmodel->brush.entities);
Cvar_RegisterVariable(&r_showdisabledepthtest);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_drawentities);
+ Cvar_RegisterVariable(&r_drawworld);
Cvar_RegisterVariable(&r_cullentities_trace);
Cvar_RegisterVariable(&r_cullentities_trace_samples);
Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
Cvar_RegisterVariable(&r_cullentities_trace_delay);
Cvar_RegisterVariable(&r_drawviewmodel);
+ Cvar_RegisterVariable(&r_drawexteriormodel);
Cvar_RegisterVariable(&r_speeds);
Cvar_RegisterVariable(&r_fullbrights);
Cvar_RegisterVariable(&r_wateralpha);
Cvar_RegisterVariable(&r_shadows_castfrombmodels);
Cvar_RegisterVariable(&r_shadows_throwdistance);
Cvar_RegisterVariable(&r_shadows_throwdirection);
+ Cvar_RegisterVariable(&r_shadows_focus);
+ Cvar_RegisterVariable(&r_shadows_shadowmapscale);
Cvar_RegisterVariable(&r_q1bsp_skymasking);
Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
Cvar_RegisterVariable(&r_transparentdepthmasking);
Cvar_RegisterVariable(&r_texture_dds_load);
Cvar_RegisterVariable(&r_texture_dds_save);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
+ Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
Cvar_RegisterVariable(&r_textureunits);
Cvar_RegisterVariable(&gl_combine);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&developer_texturelogging);
Cvar_RegisterVariable(&gl_lightmaps);
Cvar_RegisterVariable(&r_test);
- Cvar_RegisterVariable(&r_batchmode);
Cvar_RegisterVariable(&r_glsl_saturation);
Cvar_RegisterVariable(&r_framedatasize);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
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);
ent->animcache_normal3f = NULL;
ent->animcache_svector3f = NULL;
ent->animcache_tvector3f = NULL;
+ ent->animcache_vertexposition = NULL;
+ ent->animcache_vertexmesh = NULL;
+ ent->animcache_vertexpositionbuffer = NULL;
+ ent->animcache_vertexmeshbuffer = NULL;
+ }
+}
+
+void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
+{
+ int i;
+ if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
+ ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
+ if (!ent->animcache_vertexposition)
+ ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
+ if (ent->animcache_vertexposition)
+ {
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
+ // TODO: upload vertex buffer?
+ }
+ if (ent->animcache_vertexmesh)
+ {
+ memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
+ if (ent->animcache_svector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
+ if (ent->animcache_tvector3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
+ if (ent->animcache_normal3f)
+ for (i = 0;i < numvertices;i++)
+ VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
+ // TODO: upload vertex buffer?
}
}
// see if it's already cached this frame
if (ent->animcache_vertex3f)
{
- // add normals/tangents if needed
+ // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
if (wantnormals || wanttangents)
{
if (ent->animcache_normal3f)
ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
+ {
model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
+ R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
+ }
}
}
}
ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
}
if (!r_framedata_failed)
+ {
model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
+ R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
+ }
}
return !r_framedata_failed;
}
void R_AnimCache_CacheVisibleEntities(void)
{
int i;
- qboolean wantnormals = !r_showsurfaces.integer;
+ qboolean wantnormals = true;
qboolean wanttangents = !r_showsurfaces.integer;
switch(vid.renderpath)
break;
}
+ if (r_shownormals.integer)
+ wanttangents = wantnormals = true;
+
// TODO: thread this
// NOTE: R_PrepareRTLights() also caches entities
for (i = 0;i < r_refdef.scene.numentities;i++)
if (r_refdef.viewcache.entityvisible[i])
R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
-
- if (r_shadows.integer)
- for (i = 0;i < r_refdef.scene.numentities;i++)
- if (!r_refdef.viewcache.entityvisible[i])
- R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
}
//==================================================================================
entity_render_t *ent;
vec3_t tempdiffusenormal, avg;
vec_t f, fa, fd, fdd;
+ qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
// skip unseen models
- if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
+ if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
continue;
// skip bsp models
boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
+ // return true if eye is inside enlarged box
+ if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
+ return true;
+
// try center
VectorCopy(eye, start);
VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
int samples;
entity_render_t *ent;
- renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
+ renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
+ : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
+ : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
+ : RENDER_EXTERIORMODEL;
+ if (!r_drawviewmodel.integer)
+ renderimask |= RENDER_VIEWMODEL;
+ if (!r_drawexteriormodel.integer)
+ renderimask |= RENDER_EXTERIORMODEL;
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
- if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
+ if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
+ // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
{
for (i = 0;i < r_refdef.scene.numentities;i++)
{
GL_CullFace(r_refdef.view.cullface_back);
}
+/*
+================
+R_RenderView_UpdateViewVectors
+================
+*/
+static void R_RenderView_UpdateViewVectors(void)
+{
+ // break apart the view matrix into vectors for various purposes
+ // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+ // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+ VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // make an inverted copy of the view matrix for tracking sprites
+ Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+}
+
void R_RenderScene(void);
void R_RenderWaterPlanes(void);
static void R_Water_StartFrame(void)
{
int i;
- int waterwidth, waterheight, texturewidth, textureheight;
+ int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
// calculate desired texture sizes
// can't use water if the card does not support the texture size
if (!r_water.integer || r_showsurfaces.integer)
- texturewidth = textureheight = waterwidth = waterheight = 0;
+ texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
else if (vid.support.arb_texture_non_power_of_two)
{
texturewidth = waterwidth;
textureheight = waterheight;
+ camerawidth = waterwidth;
+ cameraheight = waterheight;
}
else
{
for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
+ for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
+ for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
}
// allocate textures as needed
- if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
+ if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
{
r_waterstate.maxwaterplanes = MAX_WATERPLANES;
for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
if (p->texture_reflection)
R_FreeTexture(p->texture_reflection);
p->texture_reflection = NULL;
+ if (p->texture_camera)
+ R_FreeTexture(p->texture_camera);
+ p->texture_camera = NULL;
}
memset(&r_waterstate, 0, sizeof(r_waterstate));
r_waterstate.texturewidth = texturewidth;
r_waterstate.textureheight = textureheight;
+ r_waterstate.camerawidth = camerawidth;
+ r_waterstate.cameraheight = cameraheight;
}
if (r_waterstate.texturewidth)
vec3_t normal;
vec3_t center;
mplane_t plane;
+ int cam_ent;
r_waterstate_waterplane_t *p;
texture_t *t = R_GetCurrentTexture(surface->texture);
+ cam_ent = t->camera_entity;
+ if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
+ cam_ent = 0;
+
// just use the first triangle with a valid normal for any decisions
VectorClear(normal);
for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
// find a matching plane if there is one
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
- if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
- break;
+ if(p->camera_entity == t->camera_entity)
+ if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
+ break;
if (planeindex >= r_waterstate.maxwaterplanes)
return; // nothing we can do, out of planes
// clear materialflags and pvs
p->materialflags = 0;
p->pvsvalid = false;
+ p->camera_entity = t->camera_entity;
}
// merge this surface's materialflags into the waterplane
p->materialflags |= t->currentmaterialflags;
- // merge this surface's PVS into the waterplane
- VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
- if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
- && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ if(!(p->materialflags & MATERIALFLAG_CAMERA))
{
- r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
- p->pvsvalid = true;
+ // merge this surface's PVS into the waterplane
+ VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
+ if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
+ && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ {
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
+ p->pvsvalid = true;
+ }
}
}
r_refdef_view_t myview;
int planeindex;
r_waterstate_waterplane_t *p;
+ vec3_t visorigin;
originalview = r_refdef.view;
if (p->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, 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;
}
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ if (!p->texture_camera)
+ p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
+ if (!p->texture_camera)
+ goto error;
+ }
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
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, 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;
}
// (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
+ r_waterstate.renderingrefraction = true;
r_refdef.view = myview;
+
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ R_RenderView_UpdateViewVectors();
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ }
+
PlaneClassify(&r_refdef.view.clipplane);
R_ResetViewRendering3D();
R_RenderScene();
R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_waterstate.renderingrefraction = false;
+ }
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ r_refdef.view = myview;
+
+ r_refdef.view.clipplane = p->plane;
+ VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
+ r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ r_refdef.view.width = r_waterstate.camerawidth;
+ r_refdef.view.height = r_waterstate.cameraheight;
+ r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
+ r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
+
+ if(p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ }
+
+ // reverse the cullface settings for this render
+ r_refdef.view.cullface_front = GL_FRONT;
+ r_refdef.view.cullface_back = GL_BACK;
+ // also reverse the view matrix
+ Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
+ R_RenderView_UpdateViewVectors();
+ if(p->camera_entity)
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+
+ // camera needs no clipplane
+ r_refdef.view.useclipplane = false;
+
+ PlaneClassify(&r_refdef.view.clipplane);
+
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
+ R_RenderScene();
+
+ R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_waterstate.renderingrefraction = false;
}
}
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, 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, 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
R_SetViewport(&r_bloomstate.viewport);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
- // TODO: optimize with multitexture or GLSL
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
+ // TODO: do boxfilter scale-down in shader?
R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
// we now have a bloom image in the framebuffer
r_refdef.stats.bloom++;
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
// we have a bloom image in the framebuffer
CHECKGLERROR
x *= 2;
r = bound(0, r_bloom_colorexponent.value / x, 1);
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- GL_Color(r, r, r, 1);
+ GL_Color(r,r,r,1);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
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_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 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;
}
if(range >= 1)
brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
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++)
{
if(range >= 1)
r *= (1 - x*x/(float)(range*range));
GL_Color(r, r, r, 1);
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
}
// 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);
+ GL_Color(1,1,1,1);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
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);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
GL_BlendFunc(GL_ONE, GL_ONE);
qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
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);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
qglBlendEquationEXT(GL_FUNC_ADD_EXT);
r_refdef.view.width = oldwidth;
r_refdef.view.height = oldheight;
r_refdef.view.colorscale = oldcolorscale;
- r_frame++; // used only by R_GetCurrentTexture
R_ResetViewRendering3D();
if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
{
cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
// apply the blur
- if (cl.motionbluralpha > 0)
+ if (cl.motionbluralpha > 0 && !r_refdef.envmap)
{
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Color(1, 1, 1, cl.motionbluralpha);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
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_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
}
}
{
// apply a color tint to the whole view
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
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_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
break; // no screen processing, no bloom, skip it
}
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);
+ R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
GL_BlendFunc(GL_ONE, GL_ZERO);
- R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
- R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
switch(vid.renderpath)
{
if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
- if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
if (r_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
if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
if (r_cg_permutation->fp_ViewTintColor ) cgGLSetParameter4f( r_cg_permutation->fp_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
- if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
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;
}
- R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
break;
case RENDERPATH_GL13:
{
// apply a color tint to the whole view
R_ResetViewRendering2D();
- R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
+ R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
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_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
}
break;
}
r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
+ if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
+ R_BuildFogHeightTexture();
// fog color was already set
// update the fog texture
if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
R_BuildFogTexture();
+ r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
+ r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
}
else
r_refdef.fogenabled = false;
{
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)
return;
}
- if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
+ if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
r_refdef.view.colorscale = r_hdr_scenebrightness.value;
- // break apart the view matrix into vectors for various purposes
- // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
- // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
- Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
- VectorNegate(r_refdef.view.left, r_refdef.view.right);
- // make an inverted copy of the view matrix for tracking sprites
- Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+ R_RenderView_UpdateViewVectors();
R_Shadow_UpdateWorldLightSelection();
// 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_DrawLocs(void);
static void R_DrawEntityBBoxes(void);
static void R_DrawModelDecals(void);
+extern void R_DrawModelShadows(void);
+extern void R_DrawModelShadowMaps(void);
extern cvar_t cl_decals_newsystem;
extern qboolean r_shadow_usingdeferredprepass;
void R_RenderScene(void)
{
+ qboolean shadowmapping = false;
+
+ if (r_timereport_active)
+ R_TimeReport("beginscene");
+
r_refdef.stats.renders++;
R_UpdateFogColor();
Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+ if (r_timereport_active)
+ R_TimeReport("skystartframe");
+
if (cl.csqc_vidvars.drawworld)
{
// don't let sound skip if going slow
R_TimeReport("animation");
R_Shadow_PrepareLights();
+ if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
+ R_Shadow_PrepareModelShadows();
if (r_timereport_active)
R_TimeReport("preparelights");
+ if (R_Shadow_ShadowMappingEnabled())
+ shadowmapping = true;
+
if (r_shadow_usingdeferredprepass)
R_Shadow_DrawPrepass();
R_TimeReport("modeldepth");
}
+ if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
+ {
+ R_DrawModelShadowMaps();
+ R_ResetViewRendering3D();
+ // don't let sound skip if going slow
+ if (r_refdef.scene.extraupdate)
+ S_ExtraUpdate ();
+ }
+
if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
{
r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
}
}
- R_Mesh_VertexPointer(vertex3f, 0, 0);
- R_Mesh_ColorPointer(color4f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
+ R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
}
static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
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.colormod[0];
{
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
- f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
+ f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
f2 = 1 - f1;
c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
}
}
R_Mesh_ResetTextureState();
- R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
+ R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
}
void R_DrawNoModel(entity_render_t *ent)
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;
+ if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
+ t->camera_entity = ent->entitynumber;
+ else
+ t->camera_entity = 0;
+
// switch to an alternate material if this is a q1bsp animated material
{
texture_t *texture = t;
if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
t->currentalpha *= t->r_water_wateralpha;
if(!r_waterstate.enabled || r_refdef.view.isoverlay)
- t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
+ t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
if (!(rsurface.ent_flags & RENDER_LIGHT))
t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
{
- if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
+ if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
}
else
- t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
+ t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
t->glosstexture = r_texture_black;
t->glowtexture = t->currentskinframe->glow;
t->fogtexture = t->currentskinframe->fog;
+ t->reflectmasktexture = t->currentskinframe->reflect;
if (t->backgroundnumskinframes)
{
t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
}
else
{
- t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
+ t->backgroundbasetexture = r_texture_white;
t->backgroundnmaptexture = r_texture_blanknormalmap;
t->backgroundglosstexture = r_texture_black;
t->backgroundglowtexture = NULL;
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;
void R_Mesh_ResizeArrays(int newvertices)
{
- float *base;
+ unsigned char *base;
+ size_t size;
if (rsurface.array_size >= newvertices)
return;
- if (rsurface.array_modelvertex3f)
- Mem_Free(rsurface.array_modelvertex3f);
+ if (rsurface.array_base)
+ Mem_Free(rsurface.array_base);
rsurface.array_size = (newvertices + 1023) & ~1023;
- base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
- rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
- rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
- rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
- rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
- rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
- rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
- rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
- rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
- rsurface.array_texcoord3f = base + rsurface.array_size * 24;
- rsurface.array_color4f = base + rsurface.array_size * 27;
- rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
+ size = 0;
+ size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
+ size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
+ size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
+ size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[3]);
+ size += rsurface.array_size * sizeof(float[4]);
+ size += rsurface.array_size * sizeof(float[2]);
+ size += rsurface.array_size * sizeof(float[2]);
+ size += rsurface.array_size * sizeof(float[4]);
+ size += rsurface.array_size * sizeof(int[3]);
+ size += rsurface.array_size * sizeof(unsigned short[3]);
+ rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
+ rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
+ rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
+ rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
+ rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
+ rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
+ rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
+ rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
+ rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
+ rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
+ rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
+ rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
}
void RSurf_ActiveWorldEntity(void)
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.generatedvertex = false;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
+ rsurface.modelvertexmesh = ent->animcache_vertexmesh;
+ rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
+ rsurface.modelvertexposition = ent->animcache_vertexposition;
+ rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
}
else if (wanttangents)
{
rsurface.modeltvector3f = rsurface.array_modeltvector3f;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else if (wantnormals)
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
}
else
{
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
- rsurface.generatedvertex = false;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
}
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
{
+ int i;
+
rsurface.entity = r_refdef.scene.worldentity;
rsurface.skeleton = NULL;
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = shadertime;
rsurface.ent_flags = entflags;
- rsurface.modelnum_vertices = numvertices;
- rsurface.modelnum_triangles = numtriangles;
- if (rsurface.array_size < rsurface.modelnum_vertices)
- R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
+ rsurface.modelnumvertices = numvertices;
+ rsurface.modelnumtriangles = numtriangles;
+ if (rsurface.array_size < rsurface.modelnumvertices)
+ R_Mesh_ResizeArrays(rsurface.modelnumvertices);
rsurface.matrix = *matrix;
rsurface.inversematrix = *inversematrix;
rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
rsurface.modellightmapcolor4f = color4f;
- rsurface.modellightmapcolor4f_bufferobject = 0;
+ rsurface.modellightmapcolor4f_vertexbuffer = 0;
rsurface.modellightmapcolor4f_bufferoffset = 0;
rsurface.modeltexcoordtexture2f = texcoord2f;
- rsurface.modeltexcoordtexture2f_bufferobject = 0;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
rsurface.modeltexcoordtexture2f_bufferoffset = 0;
rsurface.modeltexcoordlightmap2f = NULL;
- rsurface.modeltexcoordlightmap2f_bufferobject = 0;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
rsurface.modelelement3i = element3i;
+ rsurface.modelelement3i_indexbuffer = NULL;
+ rsurface.modelelement3i_bufferoffset = 0;
rsurface.modelelement3s = element3s;
- rsurface.modelelement3i_bufferobject = 0;
- rsurface.modelelement3s_bufferobject = 0;
+ rsurface.modelelement3s_indexbuffer = NULL;
+ rsurface.modelelement3s_bufferoffset = 0;
rsurface.modellightmapoffsets = NULL;
rsurface.modelsurfaces = NULL;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
-
- if (rsurface.modelnum_vertices && rsurface.modelelement3i)
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
+
+ if (rsurface.modelnumvertices && rsurface.modelelement3i)
{
if ((wantnormals || wanttangents) && !normal3f)
- Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelnormal3f = rsurface.array_modelnormal3f;
+ }
if (wanttangents && !svector3f)
- Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelsvector3f = rsurface.array_modelsvector3f;
+ rsurface.modeltvector3f = rsurface.array_modeltvector3f;
+ }
+ }
+
+ // now convert arrays into vertexmesh structs
+ for (i = 0;i < numvertices;i++)
+ {
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
+ if (rsurface.modelsvector3f)
+ VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
+ if (rsurface.modeltvector3f)
+ VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
+ if (rsurface.modelnormal3f)
+ VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
+ if (rsurface.modellightmapcolor4f)
+ Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
+ if (rsurface.modeltexcoordtexture2f)
+ Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
+ if (rsurface.modeltexcoordlightmap2f)
+ Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
}
}
return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
}
+void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
+{
+ int i;
+ for (i = 0;i < numelements;i++)
+ outelement3i[i] = inelement3i[i] + adjust;
+}
+
static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
-void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
+extern cvar_t gl_vbo;
+void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
int deformindex;
- int texturesurfaceindex;
+ int firsttriangle;
+ int numtriangles;
+ int firstvertex;
+ int endvertex;
+ int numvertices;
+ int surfacefirsttriangle;
+ int surfacenumtriangles;
+ int surfacefirstvertex;
+ int surfaceendvertex;
+ int surfacenumvertices;
+ int surfaceadjustvertex;
+ int needsupdate;
int i, j;
+ qboolean gaps;
+ qboolean dynamicvertex;
float amplitude;
float animpos;
float scale;
- const float *v1, *in_tc;
- float *out_tc;
float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
float waveparms[4];
q3shaderinfo_deform_t *deform;
- // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
- if (rsurface.generatedvertex)
+ const msurface_t *surface, *firstsurface;
+ r_vertexposition_t *vertexposition;
+ r_vertexmesh_t *vertexmesh;
+ if (!texturenumsurfaces)
+ return;
+ // find vertex range of this surface batch
+ gaps = false;
+ firstsurface = texturesurfacelist[0];
+ firsttriangle = firstsurface->num_firsttriangle;
+ numtriangles = 0;
+ firstvertex = endvertex = firstsurface->num_firstvertex;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surface = texturesurfacelist[i];
+ if (surface != firstsurface + i)
+ gaps = true;
+ surfacefirstvertex = surface->num_firstvertex;
+ surfaceendvertex = surfacefirstvertex + surface->num_vertices;
+ surfacenumtriangles = surface->num_triangles;
+ if (firstvertex > surfacefirstvertex)
+ firstvertex = surfacefirstvertex;
+ if (endvertex < surfaceendvertex)
+ endvertex = surfaceendvertex;
+ numtriangles += surfacenumtriangles;
+ }
+ if (!numtriangles)
+ return;
+
+ // we now know the vertex range used, and if there are any gaps in it
+ rsurface.batchfirstvertex = firstvertex;
+ rsurface.batchnumvertices = endvertex - firstvertex;
+ rsurface.batchfirsttriangle = firsttriangle;
+ rsurface.batchnumtriangles = numtriangles;
+
+ // this variable holds flags for which properties have been updated that
+ // may require regenerating vertexmesh or vertexposition arrays...
+ needsupdate = 0;
+
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
+ for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
+ {
+ switch (deform->deform)
+ {
+ default:
+ case Q3DEFORM_PROJECTIONSHADOW:
+ case Q3DEFORM_TEXT0:
+ case Q3DEFORM_TEXT1:
+ case Q3DEFORM_TEXT2:
+ case Q3DEFORM_TEXT3:
+ case Q3DEFORM_TEXT4:
+ case Q3DEFORM_TEXT5:
+ case Q3DEFORM_TEXT6:
+ case Q3DEFORM_TEXT7:
+ case Q3DEFORM_NONE:
+ break;
+ case Q3DEFORM_AUTOSPRITE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_AUTOSPRITE2:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_NORMAL:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_WAVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_BULGE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_MOVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
+ break;
+ }
+ }
+ switch(rsurface.texture->tcgen.tcgen)
+ {
+ default:
+ case Q3TCGEN_TEXTURE:
+ break;
+ case Q3TCGEN_LIGHTMAP:
+ batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
+ break;
+ case Q3TCGEN_VECTOR:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ case Q3TCGEN_ENVIRONMENT:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ }
+ if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
+ {
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ }
+
+ // check if any dynamic vertex processing must occur
+ dynamicvertex = false;
+
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
+ }
+
+ if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
+ }
+
+ if (dynamicvertex || gaps || rsurface.batchfirstvertex)
+ {
+ // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
+ if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
+ if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
+ if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
+ }
+
+ // when the model data has no vertex buffer (dynamic mesh), we need to
+ // eliminate gaps
+ if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
+ batchneed |= BATCHNEED_NOGAPS;
+
+ // if needsupdate, we have to do a dynamic vertex batch for sure
+ if (needsupdate & batchneed)
+ dynamicvertex = true;
+
+ // see if we need to build vertexmesh from arrays
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ dynamicvertex = true;
+
+ // see if we need to build vertexposition from arrays
+ if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
+ dynamicvertex = true;
+
+ // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
+ if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
+ dynamicvertex = true;
+
+ // if there is a chance of animated vertex colors, it's a dynamic batch
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ dynamicvertex = true;
+
+ rsurface.batchvertex3f = rsurface.modelvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
+ rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
+ rsurface.batchsvector3f = rsurface.modelsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
+ rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
+ rsurface.batchtvector3f = rsurface.modeltvector3f;
+ rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
+ rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
+ rsurface.batchnormal3f = rsurface.modelnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
+ rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
+ rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
+ rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
+ rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
+ rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
+ rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
+ rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ rsurface.batchvertexposition = rsurface.modelvertexposition;
+ rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
+ rsurface.batchvertexmesh = rsurface.modelvertexmesh;
+ rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
+ rsurface.batchelement3i = rsurface.modelelement3i;
+ rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
+ rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
+ rsurface.batchelement3s = rsurface.modelelement3s;
+ rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
+ rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
+
+ // if any dynamic vertex processing has to occur in software, we copy the
+ // entire surface list together before processing to rebase the vertices
+ // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
+ //
+ // if any gaps exist and we do not have a static vertex buffer, we have to
+ // copy the surface list together to avoid wasting upload bandwidth on the
+ // vertices in the gaps.
+ //
+ // if gaps exist and we have a static vertex buffer, we still have to
+ // combine the index buffer ranges into one dynamic index buffer.
+ //
+ // in all cases we end up with data that can be drawn in one call.
+
+ if (!dynamicvertex)
+ {
+ // static vertex data, just set pointers...
+ rsurface.batchgeneratedvertex = false;
+ // if there are gaps, we want to build a combined index buffer,
+ // otherwise use the original static buffer with an appropriate offset
+ if (gaps)
+ {
+ firsttriangle = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
+ numtriangles += surfacenumtriangles;
+ }
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ if (endvertex <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+ rsurface.batchfirsttriangle = firsttriangle;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+ return;
+ }
+
+ // something needs software processing, do it for real...
+ // we only directly handle interleaved array data in this case...
+ rsurface.batchgeneratedvertex = true;
+
+ // now copy the vertex data into a combined array and make an index array
+ // (this is what Quake3 does all the time)
+ //if (gaps || rsurface.batchfirstvertex)
+ {
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ // we'll only be setting up certain arrays as needed
+ if (batchneed & BATCHNEED_VERTEXPOSITION)
+ rsurface.batchvertexposition = rsurface.array_batchvertexposition;
+ if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
+ rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ if (batchneed & BATCHNEED_ARRAY_NORMAL)
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ if (batchneed & BATCHNEED_ARRAY_VECTOR)
+ {
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ }
+ if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
+ rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
+ if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
+ rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
+ numvertices = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
+ surfacenumvertices = texturesurfacelist[i]->num_vertices;
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfaceadjustvertex = numvertices - surfacefirstvertex;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ // copy only the data requested
+ if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
+ memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
+ memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
+ if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
+ {
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
+ memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
+ {
+ memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ }
+ if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
+ memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
+ if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
+ memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ }
+ RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
+ numvertices += surfacenumvertices;
+ numtriangles += surfacenumtriangles;
+ }
+
+ // generate a 16bit index array as well if possible
+ // (in general, dynamic batches fit)
+ if (numvertices <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+
+ // since we've copied everything, the batch now starts at 0
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = numvertices;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+
+ // q1bsp surfaces rendered in vertex color mode have to have colors
+ // calculated based on lightstyles
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
{
- if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
- generatenormals = true;
- for (i = 0;i < Q3MAXDEFORMS;i++)
+ // generate color arrays for the surfaces in this list
+ int c[4];
+ int scale;
+ int size3;
+ const int *offsets;
+ const unsigned char *lm;
+ numvertices = 0;
+ rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
{
- if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
+ surface = texturesurfacelist[i];
+ offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
+ surfacenumvertices = surface->num_vertices;
+ if (surface->lightmapinfo->samples)
+ {
+ for (j = 0;j < surfacenumvertices;j++)
+ {
+ lm = surface->lightmapinfo->samples + offsets[j];
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
+ VectorScale(lm, scale, c);
+ if (surface->lightmapinfo->styles[1] != 255)
+ {
+ size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
+ VectorMA(c, scale, lm, c);
+ if (surface->lightmapinfo->styles[2] != 255)
+ {
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
+ VectorMA(c, scale, lm, c);
+ if (surface->lightmapinfo->styles[3] != 255)
+ {
+ lm += size3;
+ scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ c[0] >>= 15;
+ c[1] >>= 15;
+ c[2] >>= 15;
+ Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
+ numvertices++;
+ }
+ }
+ else
{
- generatetangents = true;
- generatenormals = true;
+ for (j = 0;j < surfacenumvertices;j++)
+ {
+ Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
+ numvertices++;
+ }
}
- if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
- generatenormals = true;
- }
- if (generatenormals && !rsurface.modelnormal3f)
- {
- rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
- Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
- }
- if (generatetangents && !rsurface.modelsvector3f)
- {
- rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
- Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
- }
- }
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
+ }
+ }
+
// if vertices are deformed (sprite flares and things in maps, possibly
- // water waves, bulges and other deformations), generate them into
- // rsurface.deform* arrays from whatever the rsurface.* arrays point to
- // (may be static model data or generated data for an animated model, or
- // the previous deform pass)
+ // water waves, bulges and other deformations), modify the copied vertices
+ // in place
for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
{
switch (deform->deform)
VectorNormalize(newforward);
VectorNormalize(newright);
VectorNormalize(newup);
- // make deformed versions of only the model vertices used by the specified surfaces
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // a single autosprite surface can contain multiple sprites...
+ for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- // a single autosprite surface can contain multiple sprites...
- for (j = 0;j < surface->num_vertices - 3;j += 4)
+ VectorClear(center);
+ for (i = 0;i < 4;i++)
+ VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
+ VectorScale(center, 0.25f, center);
+ VectorCopy(rsurface.batchnormal3f + 3*j, forward);
+ VectorCopy(rsurface.batchsvector3f + 3*j, right);
+ VectorCopy(rsurface.batchtvector3f + 3*j, up);
+ for (i = 0;i < 4;i++)
{
- VectorClear(center);
- for (i = 0;i < 4;i++)
- VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
- VectorScale(center, 0.25f, center);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
- VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
- VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
- for (i = 0;i < 4;i++)
- {
- VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
- VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
- }
+ VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
+ VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
}
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_AUTOSPRITE2:
Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
VectorNormalize(newforward);
VectorNormalize(newright);
VectorNormalize(newup);
- // make deformed versions of only the model vertices used by the specified surfaces
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
const float *v1, *v2;
vec3_t start, end;
float f, l;
shortest[2];
memset(shortest, 0, sizeof(shortest));
// a single autosprite surface can contain multiple sprites...
- for (j = 0;j < surface->num_vertices - 3;j += 4)
+ for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
{
VectorClear(center);
for (i = 0;i < 4;i++)
- VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
+ VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
VectorScale(center, 0.25f, center);
// find the two shortest edges, then use them to define the
// axis vectors for rotating around the central axis
for (i = 0;i < 6;i++)
{
- v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
- v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
- Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
- Debug_PolygonEnd();
-#endif
+ v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
+ v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
l = VectorDistance2(v1, v2);
// this length bias tries to make sense of square polygons, assuming they are meant to be upright
if (v1[2] != v2[2])
}
VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
- Debug_PolygonEnd();
-#endif
// this calculates the right vector from the shortest edge
// and the up vector from the edge midpoints
VectorSubtract(shortest[0].v1, shortest[0].v2, right);
VectorNormalize(forward);
CrossProduct(up, forward, newright);
VectorNormalize(newright);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
// rotate the quad around the up axis vector, this is made
// especially easy by the fact we know the quad is flat,
// so we only have to subtract the center position and
l = DotProduct(right, center);
for (i = 0;i < 4;i++)
{
- v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
+ v1 = rsurface.batchvertex3f + 3*(j+i);
f = DotProduct(right, v1) - l;
- VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+ VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
}
}
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_NORMAL:
// deform the normals to make reflections wavey
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- float vertex[3];
- float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
- VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
- normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- VectorNormalize(normal);
- }
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
+ float vertex[3];
+ float *normal = rsurface.array_batchnormal3f + 3*j;
+ VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
+ normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ VectorNormalize(normal);
}
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_WAVE:
// deform vertex array to make wavey water and flags and such
// this is how a divisor of vertex influence on deformation
animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
+ // if the wavefunc depends on time, evaluate it per-vertex
+ if (waveparms[3])
{
- float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
- VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
- // if the wavefunc depends on time, evaluate it per-vertex
- if (waveparms[3])
- {
- waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
- scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- }
- VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
+ waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
+ scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
}
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_BULGE:
// deform vertex array to make the surface have moving bulges
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
- VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
+ scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_MOVE:
// deform vertex array
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
VectorScale(deform->parms, scale, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ for (j = 0;j < rsurface.batchnumvertices;j++)
+ VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
break;
}
}
+
// generate texcoords based on the chosen texcoord source
switch(rsurface.texture->tcgen.tcgen)
{
default:
case Q3TCGEN_TEXTURE:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
break;
case Q3TCGEN_LIGHTMAP:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ if (rsurface.batchtexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_VECTOR:
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
- {
- out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
- out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_ENVIRONMENT:
// make environment reflections using a spheremap
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
- const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
- float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
- for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
- {
- // identical to Q3A's method, but executed in worldspace so
- // carried models can be shiny too
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
- float viewer[3], d, reflected[3], worldreflected[3];
+ float viewer[3], d, reflected[3], worldreflected[3];
- VectorSubtract(rsurface.localvieworigin, vertex, viewer);
- // VectorNormalize(viewer);
+ VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
+ // VectorNormalize(viewer);
- d = DotProduct(normal, viewer);
+ d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
- reflected[0] = normal[0]*2*d - viewer[0];
- reflected[1] = normal[1]*2*d - viewer[1];
- reflected[2] = normal[2]*2*d - viewer[2];
- // note: this is proportinal to viewer, so we can normalize later
+ reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
+ reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
+ reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
+ // note: this is proportinal to viewer, so we can normalize later
- Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
- VectorNormalize(worldreflected);
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
- // note: this sphere map only uses world x and z!
- // so positive and negative y will LOOK THE SAME.
- out_tc[0] = 0.5 + 0.5 * worldreflected[1];
- out_tc[1] = 0.5 - 0.5 * worldreflected[2];
- }
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
}
// the only tcmod that needs software vertex processing is turbulent, so
{
amplitude = rsurface.texture->tcmods[0].parms[1];
animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
- {
- out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
}
- rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
- R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
-}
-void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int i, j;
- const msurface_t *surface = texturesurfacelist[0];
- const msurface_t *surface2;
- int firstvertex;
- int endvertex;
- int numvertices;
- 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)
+ if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
{
- #define MAXBATCHTRIANGLES 4096
- int batchtriangles = 0;
- static int batchelements[MAXBATCHTRIANGLES*3];
- for (i = 0;i < texturenumsurfaces;i = j)
+ // convert the modified arrays to vertex structs
+ rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
+ rsurface.batchvertexmeshbuffer = NULL;
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
+ if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
+ if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
{
- surface = texturesurfacelist[i];
- j = i + 1;
- if (surface->num_triangles > MAXBATCHTRIANGLES)
- {
- 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);
- continue;
- }
- memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
- batchtriangles = surface->num_triangles;
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- for (;j < texturenumsurfaces;j++)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
{
- surface2 = texturesurfacelist[j];
- if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
- break;
- memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
- batchtriangles += surface2->num_triangles;
- firstvertex = min(firstvertex, surface2->num_firstvertex);
- endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
+ VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
+ VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
}
- surface2 = texturesurfacelist[j-1];
- numvertices = endvertex - firstvertex;
- R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
- }
- }
- else if (r_batchmode.integer == 1)
- {
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2)
- 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 ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
+ if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
+ if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
+ Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
}
- else
+
+ if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
{
- 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);
- }
+ // convert the modified arrays to vertex structs
+ rsurface.batchvertexposition = rsurface.array_batchvertexposition;
+ rsurface.batchvertexpositionbuffer = NULL;
+ if (sizeof(r_vertexposition_t) == sizeof(float[3]))
+ memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
+ else
+ for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
+ VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
}
}
-static void RSurf_BindLightmapForSurface(const msurface_t *surface)
+void RSurf_DrawBatch(void)
+{
+ R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
+}
+
+static void RSurf_BindLightmapForBatch(void)
{
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
+ if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
+ if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.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);
+ if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
break;
case RENDERPATH_GL13:
case RENDERPATH_GL11:
- R_Mesh_TexBind(0, surface->lightmaptexture);
+ R_Mesh_TexBind(0, rsurface.lightmaptexture);
break;
}
}
-static void RSurf_BindReflectionForSurface(const msurface_t *surface)
+static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
{
- // pick the closest matching water plane and bind textures
- int planeindex, vertexindex;
+ // pick the closest matching water plane
+ int planeindex, vertexindex, bestplaneindex = -1;
float d, bestd;
vec3_t vert;
const float *v;
- r_waterstate_waterplane_t *p, *bestp;
+ r_waterstate_waterplane_t *p;
bestd = 0;
- bestp = NULL;
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
{
+ if(p->camera_entity != rsurface.texture->camera_entity)
+ continue;
d = 0;
- for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
+ for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
{
Matrix4x4_Transform(&rsurface.matrix, v, vert);
d += fabs(PlaneDiff(vert, &p->plane));
}
- if (bestd > d || !bestp)
+ if (bestd > d || bestplaneindex < 0)
{
bestd = d;
- bestp = p;
+ bestplaneindex = planeindex;
}
}
+ return bestplaneindex;
+}
+
+static void RSurf_BindReflectionForBatch(int planeindex)
+{
+ // pick the closest matching water plane and bind textures
+ r_waterstate_waterplane_t *bestp = planeindex >= 0 ? r_waterstate.waterplanes + planeindex : NULL;
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
+ if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
+ else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
+ if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
#endif
break;
case RENDERPATH_GL20:
if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
+ else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
break;
case RENDERPATH_GL13:
}
}
-static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
{
int i;
- const msurface_t *surface;
- if (r_waterstate.renderingscene)
- return;
- for (i = 0;i < texturenumsurfaces;i++)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- RSurf_BindReflectionForSurface(surface);
- 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);
- }
+ for (i = 0;i < rsurface.batchnumvertices;i++)
+ Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyFog(void)
{
int i;
- int j;
- const msurface_t *surface = texturesurfacelist[0];
- const msurface_t *surface2;
- int firstvertex;
- int endvertex;
- int numvertices;
- int numtriangles;
- if (texturenumsurfaces == 1)
- {
- RSurf_BindLightmapForSurface(surface);
- 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)
+ float f;
+ const float *v;
+ const float *c;
+ float *c2;
+ if (rsurface.passcolor4f)
{
-#define MAXBATCHTRIANGLES 4096
- int batchtriangles = 0;
- static int batchelements[MAXBATCHTRIANGLES*3];
- for (i = 0;i < texturenumsurfaces;i = j)
+ // generate color arrays
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- j = i + 1;
- if (surface->num_triangles > MAXBATCHTRIANGLES)
- {
- 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);
- continue;
- }
- memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
- batchtriangles = surface->num_triangles;
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- for (;j < texturenumsurfaces;j++)
- {
- surface2 = texturesurfacelist[j];
- if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
- break;
- memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
- batchtriangles += surface2->num_triangles;
- firstvertex = min(firstvertex, surface2->num_firstvertex);
- endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
- }
- surface2 = texturesurfacelist[j-1];
- numvertices = endvertex - firstvertex;
- R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
+ f = RSurf_FogVertex(v);
+ c2[0] = c[0] * f;
+ c2[1] = c[1] * f;
+ c2[2] = c[2] * f;
+ c2[3] = c[3];
}
}
- else if (r_batchmode.integer == 1)
+ else
{
-#if 0
- Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- surface = texturesurfacelist[i];
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2)
- break;
- Con_Printf(" %i", j - i);
- }
- Con_Printf("\n");
- Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
-#endif
- for (i = 0;i < texturenumsurfaces;i = j)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
{
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
- if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
- break;
-#if 0
- Con_Printf(" %i", j - i);
-#endif
- 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
- Con_Printf("\n");
-#endif
- }
- else
- {
- for (i = 0;i < texturenumsurfaces;i++)
- {
- surface = texturesurfacelist[i];
- RSurf_BindLightmapForSurface(surface);
- 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_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int j;
- int texturesurfaceindex;
- if (r_showsurfaces.integer == 2)
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_triangles;j++)
- {
- float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
- GL_Color(f, f, f, 1);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- }
- }
- else
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- 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);
- }
- }
-}
-
-static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int texturesurfaceindex;
- int i;
- const float *v;
- float *c2;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
- {
- c2[0] = 0.5;
- c2[1] = 0.5;
- c2[2] = 0.5;
- c2[3] = 1;
+ f = RSurf_FogVertex(v);
+ c2[0] = f;
+ c2[1] = f;
+ c2[2] = f;
+ c2[3] = 1;
}
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
{
- int texturesurfaceindex;
int i;
float f;
const float *v;
const float *c;
float *c2;
- if (rsurface.lightmapcolor4f)
- {
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = c[0] * f;
- c2[1] = c[1] * f;
- c2[2] = c[2] * f;
- c2[3] = c[3];
- }
- }
- }
- else
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = f;
- c2[1] = f;
- c2[2] = f;
- c2[3] = 1;
- }
- }
- }
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
-}
-
-static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int texturesurfaceindex;
- int i;
- float f;
- const float *v;
- const float *c;
- float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
- {
- f = RSurf_FogVertex(v);
- c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
- c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
- c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
- c2[3] = c[3];
- }
+ f = RSurf_FogVertex(v);
+ c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
+ c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
+ c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
+ c2[3] = c[3];
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
+static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
{
- int texturesurfaceindex;
int i;
const float *c;
float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
{
- 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;
- c2[1] = c[1] * g;
- c2[2] = c[2] * b;
- c2[3] = c[3] * a;
- }
+ c2[0] = c[0] * r;
+ c2[1] = c[1] * g;
+ c2[2] = c[2] * b;
+ c2[3] = c[3] * a;
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
{
- int texturesurfaceindex;
int i;
const float *c;
float *c2;
- if (!rsurface.lightmapcolor4f)
+ if (!rsurface.passcolor4f)
return;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
{
- 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;
- c2[1] = c[1] + r_refdef.scene.ambient;
- c2[2] = c[2] + r_refdef.scene.ambient;
- c2[3] = c[3];
- }
+ 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];
}
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
-static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
// TODO: optimize
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
}
-static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
// TODO: optimize applyfog && applycolor case
// just apply fog if necessary, and tint the fog color array if necessary
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
}
-static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
- int texturesurfaceindex;
- int i;
- float *c;
// TODO: optimize
- if (texturesurfacelist[0]->lightmapinfo)
- {
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
- {
- if (surface->lightmapinfo->samples)
- {
- const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
- float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
- VectorScale(lm, scale, c);
- if (surface->lightmapinfo->styles[1] != 255)
- {
- int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[2] != 255)
- {
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[3] != 255)
- {
- lm += size3;
- scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- }
- }
- }
- }
- else
- VectorClear(c);
- c[3] = 1;
- }
- }
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- }
- else
+ rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
+ rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
+ rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch();
+}
+
+static void RSurf_DrawBatch_GL11_ClampColor(void)
+{
+ int i;
+ const float *c1;
+ float *c2;
+ if (!rsurface.passcolor4f)
+ return;
+ for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
{
- rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
- rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
- rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
+ c2[0] = bound(0.0f, c1[0], 1.0f);
+ c2[1] = bound(0.0f, c1[1], 1.0f);
+ c2[2] = bound(0.0f, c1[2], 1.0f);
+ c2[3] = bound(0.0f, c1[3], 1.0f);
}
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- 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_Simple(texturenumsurfaces, texturesurfacelist);
}
-static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
+static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
{
- int texturesurfaceindex;
int i;
float f;
float alpha;
diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
alpha = *a;
- if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
+ if (VectorLength2(diffusecolor) > 0)
{
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // q3-style directional shading
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- int numverts = surface->num_vertices;
- v = rsurface.vertex3f + 3 * surface->num_firstvertex;
- n = rsurface.normal3f + 3 * surface->num_firstvertex;
- c = rsurface.array_color4f + 4 * surface->num_firstvertex;
- // q3-style directional shading
- for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
- {
- if ((f = DotProduct(n, lightdir)) > 0)
- VectorMA(ambientcolor, f, diffusecolor, c);
- else
- VectorCopy(ambientcolor, c);
- c[3] = alpha;
- }
+ if ((f = DotProduct(n, lightdir)) > 0)
+ VectorMA(ambientcolor, f, diffusecolor, c);
+ else
+ VectorCopy(ambientcolor, c);
+ c[3] = alpha;
}
*r = 1;
*g = 1;
*b = 1;
*a = 1;
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = rsurface.array_passcolor4f;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
*applycolor = false;
}
else
*r = ambientcolor[0];
*g = ambientcolor[1];
*b = ambientcolor[2];
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
}
}
-static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
{
- RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
- if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
- if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
+ RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
+}
+
+static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
+{
+ int i;
+ float f;
+ const float *v;
+ float *c;
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
+ {
+ f = 1 - RSurf_FogVertex(v);
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = f * a;
+ }
}
void RSurf_SetupDepthAndCulling(void)
// level, so don't use it then either.
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
{
- GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
if (skyrendermasked)
{
// just to make sure that braindead drivers don't draw
// anything despite that colormask...
GL_BlendFunc(GL_ZERO, GL_ONE);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
}
else
{
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
// fog sky
GL_BlendFunc(GL_ONE, GL_ZERO);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
+ GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
}
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
if (skyrendermasked)
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
}
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
- qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
- qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
-
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
+ if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
return;
-
- 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 (refract)
+ if (prepass)
{
- // render background
- GL_BlendFunc(GL_ONE, GL_ZERO);
+ // render screenspace normalmap to texture
GL_DepthMask(true);
- GL_AlphaTest(false);
-
- GL_Color(1, 1, 1, 1);
- R_Mesh_ColorPointer(NULL, 0, 0);
-
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
- 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);
- GL_LockArrays(0, 0);
-
- GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- GL_DepthMask(false);
- 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);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
+ return;
}
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
-
- 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);
- if (!prepass)
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
-
- if (refract)
- GL_DepthMask(true);
- else
- GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
+ // bind lightmap texture
- if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ // water/refraction/reflection/camera surfaces have to be handled specially
+ if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
{
- if (refract || reflect)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
- }
- else
- {
- if (refract || reflect)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ int start, end, startplaneindex;
+ for (start = 0;start < texturenumsurfaces;start = end)
+ {
+ startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
+ for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
+ ;
+ // now that we have a batch using the same planeindex, render it
+ if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
+ {
+ // render water or distortion background
+ GL_DepthMask(true);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start);
+ RSurf_BindReflectionForBatch(startplaneindex);
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
+ // blend surface on top
+ GL_DepthMask(false);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start);
+ RSurf_DrawBatch();
+ }
+ else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
+ {
+ // render surface with reflection texture as input
+ GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start);
+ RSurf_BindReflectionForBatch(startplaneindex);
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
+ }
+ }
+ return;
}
- GL_LockArrays(0, 0);
+
+ // render surface batch normally
+ GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
+ if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_BindLightmapForBatch();
+ RSurf_DrawBatch();
}
static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
// OpenGL 1.3 path - anything not completely ancient
- int texturesurfaceindex;
qboolean applycolor;
qboolean applyfog;
int layerindex;
const texturelayer_t *layer;
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
{
}
layercolor[3] = layer->color[3];
applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
- R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
case TEXTURELAYERTYPE_LITTEXTURE:
// single-pass lightmapped texture with 2x rgbscale
- //R_Mesh_TexBind(0, r_texture_white);
+ 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_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_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);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else if (rsurface.uselightmaptexture)
- RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
else
- RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_TEXTURE:
// 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_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_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);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
+ RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
// singletexture fogging
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_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
}
else
{
R_Mesh_TexBind(0, 0);
- R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
}
R_Mesh_TexBind(1, 0);
- R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[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;
- float f;
- const float *v;
- float *c;
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
- {
- f = 1 - RSurf_FogVertex(v);
- c[0] = layercolor[0];
- c[1] = layercolor[1];
- c[2] = layercolor[2];
- c[3] = f * layercolor[3];
- }
- }
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
+ RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
+ RSurf_DrawBatch();
break;
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
}
- GL_LockArrays(0, 0);
}
CHECKGLERROR
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
// OpenGL 1.1 - crusty old voodoo path
- int texturesurfaceindex;
qboolean applyfog;
int layerindex;
const texturelayer_t *layer;
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
{
}
GL_DepthMask(layer->depthmask && writedepth);
GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
switch (layer->type)
{
{
// two-pass lit texture with 2x rgbscale
// first the lightmap pass
- //R_Mesh_TexBind(0, r_texture_white);
+ 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_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
else if (rsurface.uselightmaptexture)
- RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
else
- RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
- GL_LockArrays(0, 0);
+ RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
// then apply the texture to it
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ RSurf_DrawBatch_GL11_Unlit(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
{
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);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_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);
+ RSurf_DrawBatch_GL11_VertexShade(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
- RSurf_DrawBatch_GL11_VertexColor(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);
+ RSurf_DrawBatch_GL11_VertexColor(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_TEXTURE:
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);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
+ RSurf_DrawBatch_GL11_Unlit(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_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);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
}
else
{
R_Mesh_TexBind(0, 0);
- R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
+ R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[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;
- float f;
- const float *v;
- float *c;
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
- {
- f = 1 - RSurf_FogVertex(v);
- c[0] = layer->color[0];
- c[1] = layer->color[1];
- c[2] = layer->color[2];
- c[3] = f * layer->color[3];
- }
- }
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
+ RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
+ RSurf_DrawBatch();
break;
default:
Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
}
- GL_LockArrays(0, 0);
}
CHECKGLERROR
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
}
}
-static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
+static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
{
+ int vi;
+ int j;
+ r_vertexgeneric_t *batchvertex;
float c[4];
GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_DepthMask(writedepth);
}
- rsurface.lightmapcolor4f = NULL;
-
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ if (r_showsurfaces.integer == 3)
{
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = NULL;
- rsurface.lightmapcolor4f = NULL;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
- {
- qboolean applycolor = true;
- float one = 1.0;
+ if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
- RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+ }
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
+ {
+ qboolean applycolor = true;
+ float one = 1.0;
- r_refdef.lightmapintensity = 1;
- RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
- r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
- }
- else
- {
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
- rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
- rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
- rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
- }
+ r_refdef.lightmapintensity = 1;
+ RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
+ r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
+ }
+ else
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+
+ rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
+ rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
+ rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+ }
- if(!rsurface.lightmapcolor4f)
- RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
+ if(!rsurface.passcolor4f)
+ RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
- RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
- if(r_refdef.fogenabled)
- RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch_GL11_ApplyAmbient();
+ RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
+ if(r_refdef.fogenabled)
+ RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
+ RSurf_DrawBatch_GL11_ClampColor();
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ RSurf_DrawBatch();
+ }
+ else if (!r_refdef.view.showdebug)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
+ for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ {
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
+ else if (r_showsurfaces.integer == 4)
+ {
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
+ for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
+ {
+ unsigned char c = vi << 3;
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
+ else if (r_showsurfaces.integer == 2)
+ {
+ const int *e;
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
+ for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
+ {
+ unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
+ VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
+ VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
+ VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
+ Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
+ Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
+ Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
+ }
+ else
+ {
+ int texturesurfaceindex;
+ int k;
+ const msurface_t *surface;
+ unsigned char surfacecolor4ub[4];
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
+ batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
+ vi = 0;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ k = (int)(((size_t)surface) / sizeof(msurface_t));
+ Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
+ for (j = 0;j < surface->num_vertices;j++)
+ {
+ VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
+ Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
+ vi++;
+ }
+ }
+ R_Mesh_PrepareVertices_Generic_Unlock();
+ RSurf_DrawBatch();
+ }
}
static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass)
+ if (r_showsurfaces.integer)
{
- R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
+ R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
return;
}
switch (vid.renderpath)
{
CHECKGLERROR
RSurf_SetupDepthAndCulling();
- if (r_showsurfaces.integer == 3 && !prepass)
+ if (r_showsurfaces.integer)
{
- R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
+ R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
return;
}
switch (vid.renderpath)
int texturenumsurfaces, endsurface;
texture_t *texture;
const msurface_t *surface;
- const msurface_t *texturesurfacelist[256];
+#define MAXBATCH_TRANSPARENTSURFACES 256
+ const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
// if the model is static it doesn't matter what value we give for
// wantnormals and wanttangents, so this logic uses only rules applicable
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
- rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
+ rsurface.uselightmaptexture = false;
// scan ahead until we find a different texture
endsurface = min(i + 1024, numsurfaces);
texturenumsurfaces = 0;
for (;j < endsurface;j++)
{
surface = rsurface.modelsurfaces + surfacelist[j];
- if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ if (texture != surface->texture)
break;
texturesurfacelist[texturenumsurfaces++] = surface;
}
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);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
+ RSurf_DrawBatch();
}
if (setup)
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
surface = rsurface.modelsurfaces + surfacelist[i];
texture = surface->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surface->lightmaptexture;
+ rsurface.deluxemaptexture = surface->deluxemaptexture;
rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
// scan ahead until we find a different texture
- endsurface = min(i + 1024, numsurfaces);
+ endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
texturenumsurfaces = 0;
texturesurfacelist[texturenumsurfaces++] = surface;
for (;j < endsurface;j++)
{
surface = rsurface.modelsurfaces + surfacelist[j];
- if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
+ if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
break;
texturesurfacelist[texturenumsurfaces++] = surface;
}
}
}
+static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+{
+ if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
+ return;
+ if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
+ return;
+ RSurf_SetupDepthAndCulling();
+ RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
+ RSurf_DrawBatch();
+}
+
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
if (depthonly)
- {
- if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
- return;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
- return;
- RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
+ R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
else if (prepass)
{
if (!rsurface.texture->currentnumlayers)
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_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_Color(0, 0, 0, 1);
- GL_DepthTest(writedepth);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
- 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_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthTest(true);
- RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
+ else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
+ rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
continue;
}
// simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
;
// render the range of surfaces
R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
{
CHECKGLERROR
if (depthonly)
- {
- if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
- return;
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
- return;
- RSurf_SetupDepthAndCulling();
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
+ R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
else if (prepass)
{
if (!rsurface.texture->currentnumlayers)
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_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
- RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_Color(0, 0, 0, 1);
- GL_DepthTest(writedepth);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
- else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
- {
- RSurf_SetupDepthAndCulling();
- GL_AlphaTest(false);
- R_Mesh_ColorPointer(NULL, 0, 0);
- R_Mesh_ResetTextureState();
- 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(true);
- RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
- }
- else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
+ else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
else if (!rsurface.texture->currentnumlayers)
return;
// use skin 1 instead)
texture = surfacelist[i]->texture;
rsurface.texture = R_GetCurrentTexture(texture);
+ rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
+ rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
{
continue;
}
// simply scan ahead until we find a different texture or lightmap state
- for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
;
// render the range of surfaces
R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
GL_CullFace(GL_NONE);
R_EntityMatrix(&identitymatrix);
- R_Mesh_VertexPointer(vertex3f, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
- R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
i = surfacelist[0];
GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
for (j = 0;j < 3;j++, i++)
vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
- R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
+ R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
+ R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
}
void R_DrawLocs(void)
tridecal_t *decal;
tridecal_t *decals;
int i;
- int maxdecals;
// expand or initialize the system
if (decalsystem->maxdecals <= decalsystem->numdecals)
}
// grab a decal and search for another free slot for the next one
- maxdecals = decalsystem->maxdecals;
decals = decalsystem->decals;
decal = decalsystem->decals + (i = decalsystem->freedecal++);
for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
const msurface_t *surfaces;
const int *surfacelist;
const texture_t *texture;
- int numvertices;
int numtriangles;
int numsurfacelist;
int surfacelistindex;
int surfaceindex;
int triangleindex;
- int decalsurfaceindex;
int cornerindex;
int index;
int numpoints;
float localmins[3];
float localmaxs[3];
float localsize;
- float ilocalsize;
float v[9][3];
float tc[9][2];
float c[9][4];
Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
VectorNormalize(localnormal);
localsize = worldsize*rsurface.inversematrixscale;
- ilocalsize = 1.0f / localsize;
localmins[0] = localorigin[0] - localsize;
localmins[1] = localorigin[1] - localsize;
localmins[2] = localorigin[2] - localsize;
{
surfaceindex = surfacelist[surfacelistindex];
surface = surfaces + surfaceindex;
+ // check cull box first because it rejects more than any other check
+ if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
+ continue;
// skip transparent surfaces
texture = surface->texture;
if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
continue;
if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
continue;
- if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
- continue;
- decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
- numvertices = surface->num_vertices;
numtriangles = surface->num_triangles;
- for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
+ for (triangleindex = 0, e = rsurface.modelelement3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
{
for (cornerindex = 0;cornerindex < 3;cornerindex++)
{
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;
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
t2f[5] = decal->texcoord2f[2][1];
// update vertex positions for animated models
- if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
+ if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
{
e = rsurface.modelelement3i + 3*decal->triangleindex;
- VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
- VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
- VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
+ VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
+ VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
+ VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
}
else
{
VectorCopy(decal->vertex3f[2], v3f + 6);
}
+ if (r_refdef.fogenabled)
+ {
+ alpha = RSurf_FogVertex(v3f);
+ VectorScale(c4f, alpha, c4f);
+ alpha = RSurf_FogVertex(v3f + 3);
+ VectorScale(c4f + 4, alpha, c4f + 4);
+ alpha = RSurf_FogVertex(v3f + 6);
+ VectorScale(c4f + 8, alpha, c4f + 8);
+ }
+
v3f += 9;
c4f += 12;
t2f += 6;
{
r_refdef.stats.drawndecals += numtris;
- if (r_refdef.fogenabled)
- {
- switch(vid.renderpath)
- {
- case RENDERPATH_GL20:
- case RENDERPATH_CGGL:
- case RENDERPATH_GL13:
- case RENDERPATH_GL11:
- for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
- {
- alpha = RSurf_FogVertex(v3f);
- c4f[0] *= alpha;
- c4f[1] *= alpha;
- c4f[2] *= alpha;
- }
- break;
- }
- }
-
// now render the decals all at once
// (this assumes they all use one particle font texture!)
RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
R_Mesh_ResetTextureState();
- R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
- R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
- R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
+ R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
GL_CullFace(GL_NONE);
GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
- GL_LockArrays(0, numtris * 3);
- R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
- GL_LockArrays(0, 0);
+ R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
}
}
}
}
+extern cvar_t mod_collision_bih;
void R_DrawDebugModel(void)
{
entity_render_t *ent = rsurface.entity;
int i, j, k, l, flagsmask;
- const int *elements;
- q3mbrush_t *brush;
const msurface_t *surface;
dp_model_t *model = ent->model;
vec3_t v;
flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
- R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_ResetTextureState();
R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
GL_DepthRange(0, 1);
GL_DepthMask(false);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
+ if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
{
+ int triangleindex;
+ int bihleafindex;
+ qboolean cullbox = ent == r_refdef.scene.worldentity;
+ const q3mbrush_t *brush;
+ const bih_t *bih = &model->collision_bih;
+ const bih_leaf_t *bihleaf;
+ float vertex3f[3][3];
GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
- for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
- {
- if (brush->colbrushf && brush->colbrushf->numtriangles)
- {
- R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
- GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
- }
- }
- for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+ cullbox = false;
+ for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
{
- if (surface->num_collisiontriangles)
+ if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
+ continue;
+ switch (bihleaf->type)
{
- R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
- GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
+ case BIH_BRUSH:
+ brush = model->brush.data_brushes + bihleaf->itemindex;
+ if (brush->colbrushf && brush->colbrushf->numtriangles)
+ {
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
+ R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
+ }
+ break;
+ case BIH_COLLISIONTRIANGLE:
+ triangleindex = bihleaf->itemindex;
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
+ VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+ break;
+ case BIH_RENDERTRIANGLE:
+ triangleindex = bihleaf->itemindex;
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
+ VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
+ GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
+ R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
+ R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+ break;
}
}
}
rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
- RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
+ RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
if (r_showtris.value > 0)
{
if (!rsurface.texture->currentlayers->depthmask)
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);
+ R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
- 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);
+ RSurf_DrawBatch();
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
CHECKGLERROR
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 0, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
+ VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglEnd();
CHECKGLERROR
}
- if (r_shownormals.value > 0)
+ if (r_shownormals.value > 0 && rsurface.batchsvector3f)
{
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 0, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(0, r_refdef.view.colorscale, 0, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
qglBegin(GL_LINES);
for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
{
- VectorCopy(rsurface.vertex3f + l * 3, v);
+ VectorCopy(rsurface.batchvertex3f + l * 3, v);
GL_Color(0, 0, r_refdef.view.colorscale, 1);
qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
+ VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
GL_Color(r_refdef.view.colorscale, 1, 1, 1);
qglVertex3f(v[0], v[1], v[2]);
}
const msurface_t **r_surfacelist = NULL;
void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
{
- int i, j, endj, f, flagsmask;
- texture_t *t;
+ int i, j, endj, flagsmask;
dp_model_t *model = r_refdef.scene.worldmodel;
msurface_t *surfaces;
unsigned char *update;
return;
}
- f = 0;
- t = NULL;
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
{
- int i, j, endj, f, flagsmask;
- texture_t *t;
+ int i, j, endj, flagsmask;
dp_model_t *model = ent->model;
msurface_t *surfaces;
unsigned char *update;
else if (prepass)
RSurf_ActiveModelEntity(ent, true, true, true);
else if (depthonly)
- RSurf_ActiveModelEntity(ent, false, false, false);
+ {
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
+ break;
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
+ break;
+ }
+ }
else
{
switch (vid.renderpath)
return;
}
- f = 0;
- t = NULL;
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
texture.currentskinframe = skinframe;
texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
+ texture.offsetmapping = OFFSETMAPPING_OFF;
+ texture.offsetscale = 1;
texture.specularscalemod = 1;
texture.specularpowermod = 1;
// now render it
rsurface.texture = R_GetCurrentTexture(surface.texture);
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
}
// now render it
rsurface.texture = R_GetCurrentTexture(surface.texture);
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
}