#include "polygon.h"
#include "image.h"
#include "ft2.h"
+#include "csprogs.h"
+#include "cl_video.h"
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
+cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
+cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
+cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
+cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
cvar_t 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"};
rtexture_t *r_texture_whitecube;
rtexture_t *r_texture_normalizationcube;
rtexture_t *r_texture_fogattenuation;
+rtexture_t *r_texture_fogheighttexture;
rtexture_t *r_texture_gammaramps;
unsigned int r_texture_gammaramps_serial;
//rtexture_t *r_texture_fogintensity;
r_refdef.fog_end = 16384;
r_refdef.fog_height = 1<<30;
r_refdef.fog_fadedepth = 128;
+ memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
}
static void R_BuildBlankTextures(void)
data[1] = 128; // normal Y
data[0] = 255; // normal Z
data[3] = 128; // height
- r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
+ r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
data[0] = 255;
data[1] = 255;
data[2] = 255;
data[3] = 255;
- r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
+ r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
data[0] = 128;
data[1] = 128;
data[2] = 128;
data[3] = 255;
- r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
+ r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 255;
- r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
+ r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
}
static void R_BuildNoTexture(void)
}
}
}
- r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
+ r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
}
static void R_BuildWhiteCube(void)
{
unsigned char data[6*1*1*4];
memset(data, 255, sizeof(data));
- r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
}
static void R_BuildNormalizationCube(void)
}
}
}
- r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
+ r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
Mem_Free(data);
}
}
else
{
- r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
+ r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
//r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
}
}
+static 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, NULL);
+ 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, -1, 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"
" 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"
"uniform sampler2D Texture_Shirt;\n"
"#endif\n"
"#ifdef USEFOG\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+"uniform sampler2D Texture_FogHeightTexture;\n"
+"#endif\n"
"uniform sampler2D Texture_FogMask;\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"uniform float FogRangeRecip;\n"
"uniform float FogPlaneViewDist;\n"
"uniform float FogHeightFade;\n"
-"float FogVertex(void)\n"
+"vec3 FogVertex(vec3 surfacecolor)\n"
"{\n"
" vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
" float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
" float fogfrac;\n"
-"#ifdef USEFOGOUTSIDE\n"
-" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"#ifdef USEFOGHEIGHTTEXTURE\n"
+" vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
+" fogfrac = fogheightpixel.a;\n"
+" return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#else\n"
+"# ifdef USEFOGOUTSIDE\n"
+" fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
+"# else\n"
" fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
+"# endif\n"
+" return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
"#endif\n"
-" return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
"}\n"
"#endif\n"
"\n"
"\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"# ifdef USESHADOWMAPORTHO\n"
-"# define GetShadowMapTC2D(dir) (min(dir, vec3(ShadowMap_Parameters.zw, 1.0)))\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"
-" 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"
+" vec3 adir = abs(dir);\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"
"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"
+" 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"
"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"
"\n"
"# endif\n"
"# ifdef USESHADOWMAPORTHO\n"
-" return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
"# else\n"
" return f;\n"
"# endif\n"
"# else\n"
"# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
"# endif\n"
-" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
-" center *= ShadowMap_TextureScale;\n"
+" vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
+"# if USESHADOWMAPPCF > 1\n"
+" vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
+" vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
+" vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
+" vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
+" vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
+" vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
+" vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
+" vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
+" vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
+" vec4 locols = vec4(group1.ab, group3.ab);\n"
+" vec4 hicols = vec4(group7.rg, group9.rg);\n"
+" locols.yz += group2.ab;\n"
+" hicols.yz += group8.rg;\n"
+" vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
+" vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
+" mix(locols, hicols, offset.y);\n"
+" vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
+" cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
+" f = dot(cols, vec4(1.0/25.0));\n"
+"# else\n"
" vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
" vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
" vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
" vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"# endif\n"
"# else\n"
"# ifdef GL_EXT_gpu_shader4\n"
"# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
"# endif\n"
"# endif\n"
"# ifdef USESHADOWMAPORTHO\n"
-" return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+" return mix(ShadowMap_Parameters.w, 1.0, f);\n"
"# else\n"
" return f;\n"
"# endif\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= myhalf(FogVertex());\n"
-"#else\n"
-" color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
+"#if defined(USEREFLECTION)\n"
+"#undef USESHADOWMAPORTHO\n"
+"#endif\n"
+"\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
+"#endif\n"
+"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
"#ifdef VERTEX_SHADER\n"
"void main\n"
"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"
"#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"
"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"# ifdef USESHADOWMAPORTHO\n"
-"# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, float3(ShadowMap_Parameters.zw, 1.0)))\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"
-" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-" float ma = max(max(adir.x, adir.y), adir.z);\n"
-" float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
+" float3 adir = abs(dir);\n"
+" float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
+" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
+" return float3(lerp(dir.xy, 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"
-" float2 tc;\n"
-" float2 offset;\n"
-" float ma;\n"
-" if (adir.x > adir.y)\n"
-" {\n"
-" if (adir.x > adir.z) // X\n"
-" {\n"
-" ma = adir.x;\n"
-" tc = dir.zy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-" else\n"
-" {\n"
-" if (adir.y > adir.z) // Y\n"
-" {\n"
-" ma = adir.y;\n"
-" tc = dir.xz;\n"
-" offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
-" }\n"
-" else // Z\n"
-" {\n"
-" ma = adir.z;\n"
-" tc = dir.xy;\n"
-" offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
-" }\n"
-" }\n"
-"\n"
-" float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
-" stc.xy += offset * ShadowMap_Parameters.y;\n"
-" stc.z += ShadowMap_Parameters.z;\n"
-" return stc;\n"
+" 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) || defined(USESHADOWMAPORTHO)\n"
+"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"#ifdef USESHADOWMAPCUBE\n"
"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"\n"
"# endif\n"
"# ifdef USESHADOWMAPORTHO\n"
-" return lerp(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
"# else\n"
" return f;\n"
"# endif\n"
"# endif\n"
"# endif\n"
"# ifdef USESHADOWMAPORTHO\n"
-" return lerp(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
+" return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
"# else\n"
" return f;\n"
"# endif\n"
"uniform sampler2D Texture_ScreenDepth,\n"
"uniform sampler2D Texture_ScreenNormalMap,\n"
"\n"
+"#ifdef USECUBEFILTER\n"
+"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"uniform samplerRECTShadow Texture_ShadowMapRect,\n"
"{\n"
" // calculate viewspace pixel position\n"
" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-" ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
+" //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
" float3 position;\n"
" position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
"out 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"
"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"out float3 ShadowMapTC : TEXCOORD8,\n"
+"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"out float4 gl_Position : POSITION\n"
")\n"
"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"
"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"float3 ShadowMapTC : TEXCOORD8\n"
+"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"\n"
"uniform sampler2D Texture_Normal,\n"
"uniform sampler2D Texture_Shirt,\n"
"#endif\n"
"#ifdef USEFOG\n"
+"uniform sampler2D Texture_FogHeightTexture,\n"
"uniform sampler2D Texture_FogMask,\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"#endif\n"
"\n"
"#ifdef USEREFLECTCUBE\n"
-" vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
-" vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
-" vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
+" 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"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#else\n"
-" color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
- SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
- SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
- SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
- SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
- SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
+ SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
+ SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
+ SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+ SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+ SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESATURATION\n", " saturation"},
{"#define USEFOGINSIDE\n", " foginside"},
{"#define USEFOGOUTSIDE\n", " fogoutside"},
+ {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
int loc_Texture_SecondaryGlow;
int loc_Texture_Pants;
int loc_Texture_Shirt;
+ int loc_Texture_FogHeightTexture;
int loc_Texture_FogMask;
int loc_Texture_Lightmap;
int loc_Texture_Deluxemap;
p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
+ if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
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);
CGparameter fp_Texture_SecondaryGlow;
CGparameter fp_Texture_Pants;
CGparameter fp_Texture_Shirt;
+ CGparameter fp_Texture_FogHeightTexture;
CGparameter fp_Texture_FogMask;
CGparameter fp_Texture_Lightmap;
CGparameter fp_Texture_Deluxemap;
p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
+ p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
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
// distorted background
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
mode = SHADERMODE_WATER;
- else
+ else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
mode = SHADERMODE_REFRACTION;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
+ else
+ {
+ mode = SHADERMODE_GENERIC;
+ permutation |= SHADERPERMUTATION_DIFFUSE;
+ }
GL_AlphaTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
mode = SHADERMODE_DEFERREDGEOMETRY;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
}
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
{
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
if (r_shadow_usingshadowmaprect)
permutation |= SHADERPERMUTATION_REFLECTION;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
{
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
if (r_shadow_usingshadowmaprect)
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
{
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
if (r_shadow_usingshadowmaprect)
permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
- }
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(NULL, 0, 0);
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
{
if (r_glsl_offsetmapping.integer)
{
- permutation |= SHADERPERMUTATION_OFFSETMAPPING;
- if (r_glsl_offsetmapping_reliefmapping.integer)
- permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
+ {
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING;
+ if (r_glsl_offsetmapping_reliefmapping.integer)
+ permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
+ }
}
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
+ if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
{
permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
if (r_shadow_usingshadowmaprect)
if (r_shadow_glossexact.integer)
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (r_glsl_deluxemapping.integer >= 2)
{
if (r_shadow_glossexact.integer)
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else if (rsurface.uselightmaptexture)
{
// ordinary lightmapping (q1bsp, q3bsp)
mode = SHADERMODE_LIGHTMAP;
- R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
- if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- else
- R_Mesh_ColorPointer(NULL, 0, 0);
}
else
{
// ordinary vertex coloring (q3bsp)
mode = SHADERMODE_VERTEXCOLOR;
- R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
- R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
- }
- R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
- if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
- {
- R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
- R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
- R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
- }
- else
- {
- R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
- R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
}
GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
switch(vid.renderpath)
{
case RENDERPATH_GL20:
+ 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_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_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 || r_shadow_usingshadowmaportho)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
- if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
- if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
+ 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 );
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->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 || r_shadow_usingshadowmaportho)
+ if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
{
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_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
}
+extern cvar_t gl_picmip;
skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
{
int j;
qboolean ddshasalpha = false;
float ddsavgcolor[4];
char basename[MAX_QPATH];
+ int miplevel = R_PicmipForFlags(textureflags);
+ int savemiplevel = miplevel;
+ int mymiplevel;
if (cls.state == ca_dedicated)
return NULL;
Image_StripImageExtension(name, basename, sizeof(basename));
// check for DDS texture file first
- if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
+ if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
{
- basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
+ basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel);
if (basepixels == NULL)
return NULL;
}
+ // FIXME handle miplevel
+
if (developer_loading.integer)
Con_Printf("loading skin \"%s\"\n", name);
skinframe->hasalpha = ddshasalpha;
VectorCopy(ddsavgcolor, skinframe->avgcolor);
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
+ skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
//Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
}
else
{
basepixels_width = image_width;
basepixels_height = image_height;
- skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
if (textureflags & TEXF_ALPHA)
{
for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
pixels[j+2] = 255;
pixels[j+3] = basepixels[j+3];
}
- skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
Mem_Free(pixels);
}
}
if (r_loaddds)
{
+ mymiplevel = savemiplevel;
if (r_loadnormalmap)
- skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
- skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
+ skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, mymiplevel);
+ skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
if (r_loadgloss)
- skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
- skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
- skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
- skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
+ skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+ skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+ skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
+ skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
}
// _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, false)) != NULL)
+ mymiplevel = savemiplevel;
+ if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != 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);
+ 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), mymiplevel, NULL);
Mem_Free(pixels);
pixels = NULL;
}
- else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
+ else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), 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), mymiplevel, NULL);
Mem_Free(pixels);
Mem_Free(bumppixels);
}
{
pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
+ skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
Mem_Free(pixels);
}
if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
// _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, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
+ mymiplevel = savemiplevel;
+ if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
{
- 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);
+ 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), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
Mem_Free(pixels);pixels = NULL;
}
- if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ mymiplevel = savemiplevel;
+ if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- 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);
+ 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), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
Mem_Free(pixels);
pixels = NULL;
}
- if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ mymiplevel = savemiplevel;
+ if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- 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);
+ 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), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
Mem_Free(pixels);
pixels = NULL;
}
- if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ mymiplevel = savemiplevel;
+ if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- 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);
+ 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), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
Mem_Free(pixels);
pixels = NULL;
}
- if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
+ mymiplevel = savemiplevel;
+ if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
{
- 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);
+ 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), mymiplevel, NULL);
if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
Mem_Free(pixels);
temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
temp2 = temp1 + width * height * 4;
Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
Mem_Free(temp1);
}
- skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
if (textureflags & TEXF_ALPHA)
{
for (i = 3;i < width * height * 4;i += 4)
memcpy(fogpixels, skindata, width * height * 4);
for (i = 0;i < width * height * 4;i += 4)
fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
Mem_Free(fogpixels);
}
}
// use either a custom palette or the quake palette
Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
- skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
+ skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
Mem_Free(temp1);
}
if (skinframe->qgenerateglow)
{
skinframe->qgenerateglow = false;
- skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
+ skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
}
if (colormapped)
{
skinframe->qgeneratebase = false;
- skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
- skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
- skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
+ skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
+ skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
+ skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
}
else
{
skinframe->qgeneratemerged = false;
- skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
+ skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
}
if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
if (developer_loading.integer)
Con_Printf("loading embedded 8bit image \"%s\"\n", name);
- skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
+ skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette);
if (textureflags & TEXF_ALPHA)
{
for (i = 0;i < width * height;i++)
}
}
if (r_loadfog && skinframe->hasalpha)
- skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
+ skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, alphapalette);
}
R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
// 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)))
+ if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL)))
{
// an image loaded, make sure width and height are equal
if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
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);
+ cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, -1, NULL);
Mem_Free(cubemappixels);
}
else
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
R_BuildNormalizationCube();
}
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
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;
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(&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)
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
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_COLORBUFFER, 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, -1, 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, -1, 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_COLORBUFFER, 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, -1, 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_COLORBUFFER, 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, -1, 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_COLORBUFFER, 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, -1, 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
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);
}
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);
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)
{
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;
}
else
{
- r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
+ r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
}
}
}
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();
{
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");
R_TimeReport("modeldepth");
}
- if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
+ if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadowMaps();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
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)
layer->color[3] = a;
}
+static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
+{
+ if(parms[0] == 0 && parms[1] == 0)
+ return false;
+ if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
+ if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
+ return false;
+ return true;
+}
+
static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
{
double index, f;
index = parms[2] + r_refdef.scene.time * parms[3];
index -= floor(index);
- switch (func)
+ switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
{
default:
case Q3WAVEFUNC_NONE:
f = -(1 - f);
break;
}
- return (float)(parms[0] + parms[1] * f);
+ f = parms[0] + parms[1] * f;
+ if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
+ f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
+ return (float) f;
}
void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
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;
}
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;
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)
// return;
rsurface.entity = r_refdef.scene.worldentity;
rsurface.skeleton = NULL;
+ memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = 0;
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)
// return;
rsurface.entity = (entity_render_t *)ent;
rsurface.skeleton = ent->skeleton;
+ memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
rsurface.ent_skinnum = ent->skinnum;
rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
rsurface.ent_shadertime = ent->shadertime;
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++)
{
- if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
- generatenormals = true;
- for (i = 0;i < Q3MAXDEFORMS;i++)
- {
- if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
- {
- generatetangents = true;
- generatenormals = true;
- }
- 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)
+ 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)
case Q3DEFORM_NONE:
break;
case Q3DEFORM_AUTOSPRITE:
- Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
- Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
- Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
- 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];
- // a single autosprite surface can contain multiple sprites...
- for (j = 0;j < surface->num_vertices - 3;j += 4)
+ 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:
+ if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
+ break; // if wavefunc is a nop, ignore this transform
+ 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:
+ if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
+ break; // if wavefunc is a nop, ignore this transform
+ 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)
{
- 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++)
+ 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)
+ {
+ // 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++)
+ {
+ 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)
{
- 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);
+ 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
+ {
+ for (j = 0;j < surfacenumvertices;j++)
+ {
+ Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
+ numvertices++;
+ }
+ }
+ }
+ }
+
+ // if vertices are deformed (sprite flares and things in maps, possibly
+ // 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)
+ {
+ 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:
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
+ VectorNormalize(newforward);
+ VectorNormalize(newright);
+ VectorNormalize(newup);
+ // a single autosprite surface can contain multiple sprites...
+ for (j = 0;j < rsurface.batchnumvertices - 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++)
+ {
+ 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
waveparms[1] = deform->waveparms[1];
waveparms[2] = deform->waveparms[2];
waveparms[3] = deform->waveparms[3];
+ if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
+ break; // if wavefunc is a nop, don't make a dynamic vertex array
// 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
+ if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
+ break; // if wavefunc is a nop, don't make a dynamic 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)
- 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;
- 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];
- 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);
- 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);
- R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
- }
- else if (r_batchmode.integer == 2)
- {
-#define MAXBATCHTRIANGLES 4096
- int batchtriangles = 0;
- static int batchelements[MAXBATCHTRIANGLES*3];
- for (i = 0;i < texturenumsurfaces;i = j)
- {
- 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);
- }
- }
- else if (r_batchmode.integer == 1)
- {
-#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)
- {
- 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;
- 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);
- 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);
- 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;
- }
- }
- rsurface.lightmapcolor4f = rsurface.array_color4f;
- rsurface.lightmapcolor4f_bufferobject = 0;
- rsurface.lightmapcolor4f_bufferoffset = 0;
-}
-
-static void RSurf_DrawBatch_GL11_ApplyFog(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)
{
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // 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)
{
- 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];
- }
+ 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++)
+ for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
{
- 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;
- }
+ 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_ApplyFogToFinishedVertexColors(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)
+ 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)
{
- if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
+ if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
return;
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
if (prepass)
{
// render screenspace normalmap to texture
GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
- }
- else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
- {
- // render water or distortion background, then blend surface on top
- GL_DepthMask(true);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
- GL_DepthMask(false);
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
- if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch();
+ return;
}
- else
+
+ // bind lightmap texture
+
+ // 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)
{
- // render surface normally
- GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
- R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
- RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
- else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ 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;
}
+
+ // 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)
{
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);
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)
{
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);
+ 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);
}
}
-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 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
+ 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 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
+ 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)
if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
continue;
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++)
{
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);
- R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 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;
- 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);
- 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]);
}
return;
}
+ rsurface.lightmaptexture = NULL;
+ rsurface.deluxemaptexture = NULL;
rsurface.uselightmaptexture = false;
rsurface.texture = NULL;
rsurface.rtlight = NULL;
return;
}
+ 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);
}