#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 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)
}
}
+static void R_BuildFogHeightTexture(void)
+{
+ unsigned char *inpixels;
+ int size;
+ int x;
+ int y;
+ int j;
+ float c[4];
+ float f;
+ inpixels = NULL;
+ strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
+ if (r_refdef.fogheighttexturename[0])
+ inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
+ if (!inpixels)
+ {
+ r_refdef.fog_height_tablesize = 0;
+ if (r_texture_fogheighttexture)
+ R_FreeTexture(r_texture_fogheighttexture);
+ r_texture_fogheighttexture = NULL;
+ if (r_refdef.fog_height_table2d)
+ Mem_Free(r_refdef.fog_height_table2d);
+ r_refdef.fog_height_table2d = NULL;
+ if (r_refdef.fog_height_table1d)
+ Mem_Free(r_refdef.fog_height_table1d);
+ r_refdef.fog_height_table1d = NULL;
+ return;
+ }
+ size = image_width;
+ r_refdef.fog_height_tablesize = size;
+ r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
+ r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
+ memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
+ Mem_Free(inpixels);
+ // LordHavoc: now the magic - what is that table2d for? it is a cooked
+ // average fog color table accounting for every fog layer between a point
+ // and the camera. (Note: attenuation is handled separately!)
+ for (y = 0;y < size;y++)
+ {
+ for (x = 0;x < size;x++)
+ {
+ Vector4Clear(c);
+ f = 0;
+ if (x < y)
+ {
+ for (j = x;j <= y;j++)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ else
+ {
+ for (j = x;j >= y;j--)
+ {
+ Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
+ f++;
+ }
+ }
+ f = 1.0f / f;
+ r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
+ r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
+ }
+ }
+ r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
+}
+
//=======================================================================================================================================================
static const char *builtinshaderstring =
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
" 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"
"vec4 GetShadowMapTCCube(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-" return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= myhalf(FogVertex());\n"
-"#else\n"
-" color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
-"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
+"// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
+"#if defined(USEREFLECTION)\n"
+"#undef USESHADOWMAPORTHO\n"
+"#endif\n"
+"\n"
+"#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
"# define USEFOG\n"
"#endif\n"
"#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
"#define USEEYEVECTOR\n"
"#endif\n"
"\n"
+"#ifdef FRAGMENT_SHADER\n"
+"#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
+"#endif\n"
+"\n"
"#ifdef MODE_DEPTH_OR_SHADOW\n"
"#ifdef VERTEX_SHADER\n"
"void main\n"
"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"
" float3 adir = abs(dir);\n"
" float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
" float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
-" return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
+" return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
"}\n"
"# else\n"
"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
"}\n"
"# endif\n"
"# endif\n"
-"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
+"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
"\n"
"#ifdef USESHADOWMAPCUBE\n"
"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
"{\n"
" float3 adir = abs(dir);\n"
-" return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
"}\n"
"#endif\n"
"\n"
"# ifdef USESHADOWMAPPCF\n"
"# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
"# ifdef GL_ARB_texture_gather\n"
-"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
-"# else\n"
-"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
-"# endif\n"
-" float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
-"# if USESHADOWMAPPCF > 1\n"
-" float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
-" float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
-" float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
-" float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
-" float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
-" float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
-" float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
-" float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
-" float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
-" float4 locols = float4(group1.ab, group3.ab);\n"
-" float4 hicols = float4(group7.rg, group9.rg);\n"
-" locols.yz += group2.ab;\n"
-" hicols.yz += group8.rg;\n"
-" float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
-" float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
-" lerp(locols, hicols, offset.y);\n"
-" float4 cols = group5 + float4(group2.rg, group8.ab);\n"
-" cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
-" f = dot(cols, float4(1.0/25.0));\n"
+"# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
"# else\n"
-" float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
-" float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
-" float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
-" float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
-" float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
-" lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
-" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
+"# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
"# endif\n"
+" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
+" center *= ShadowMap_TextureScale;\n"
+" float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
+" float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
+" float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
+" float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
+" float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
+" lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
+" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
"# else\n"
"# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
"# if USESHADOWMAPPCF > 1\n"
"uniform sampler2D Texture_ScreenDepth,\n"
"uniform sampler2D Texture_ScreenNormalMap,\n"
"\n"
+"#ifdef USECUBEFILTER\n"
+"uniform samplerCUBE Texture_Cube,\n"
+"#endif\n"
+"\n"
"#ifdef USESHADOWMAPRECT\n"
"# ifdef USESHADOWSAMPLER\n"
"uniform samplerRECTShadow Texture_ShadowMapRect,\n"
"{\n"
" // calculate viewspace pixel position\n"
" float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
-" ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
+" //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
" float3 position;\n"
" position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
" position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
"out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"out float3 ShadowMapTC : TEXCOORD8,\n"
+"out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"out float4 gl_Position : POSITION\n"
")\n"
"float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
"#endif\n"
"#ifdef USESHADOWMAPORTHO\n"
-"float3 ShadowMapTC : TEXCOORD8,\n"
+"float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
"#endif\n"
"\n"
"uniform sampler2D Texture_Normal,\n"
"uniform sampler2D Texture_Shirt,\n"
"#endif\n"
"#ifdef USEFOG\n"
+"uniform sampler2D Texture_FogHeightTexture,\n"
"uniform sampler2D Texture_FogMask,\n"
"#endif\n"
"#ifdef USELIGHTMAP\n"
"#endif\n"
"\n"
"#ifdef USEFOG\n"
-"#ifdef MODE_LIGHTSOURCE\n"
-" color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#else\n"
-" color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
-"#endif\n"
+" color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
"#endif\n"
"\n"
" // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
- SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
- SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
- SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
- SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
- SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
- SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
- SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
- SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
- SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
- SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
- SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
- SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
- SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
- SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
- SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
- SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
+ SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
+ SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
+ SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
+ SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
+ SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
+ SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
+ SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
+ SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
+ SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
+ SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
+ SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
+ SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
+ SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
+ SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
+ SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
+ SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
+ SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESATURATION\n", " saturation"},
{"#define USEFOGINSIDE\n", " foginside"},
{"#define USEFOGOUTSIDE\n", " fogoutside"},
+ {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
int loc_Texture_SecondaryGlow;
int loc_Texture_Pants;
int loc_Texture_Shirt;
+ int loc_Texture_FogHeightTexture;
int loc_Texture_FogMask;
int loc_Texture_Lightmap;
int loc_Texture_Deluxemap;
p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
+ p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
+ if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
CGparameter fp_Texture_SecondaryGlow;
CGparameter fp_Texture_Pants;
CGparameter fp_Texture_Shirt;
+ CGparameter fp_Texture_FogHeightTexture;
CGparameter fp_Texture_FogMask;
CGparameter fp_Texture_Lightmap;
CGparameter fp_Texture_Deluxemap;
p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
+ p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
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);
}
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);
}
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 (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
permutation |= SHADERPERMUTATION_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);
}
permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
}
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
permutation |= SHADERPERMUTATION_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 (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
permutation |= SHADERPERMUTATION_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 (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
permutation |= SHADERPERMUTATION_GLOW;
if (r_refdef.fogenabled)
- permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
+ permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
if (r_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_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 );
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
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
R_BuildNormalizationCube();
}
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
//r_texture_fogintensity = NULL;
memset(&r_bloomstate, 0, sizeof(r_bloomstate));
r_texture_whitecube = NULL;
r_texture_normalizationcube = NULL;
r_texture_fogattenuation = NULL;
+ r_texture_fogheighttexture = NULL;
r_texture_gammaramps = NULL;
r_texture_numcubemaps = 0;
//r_texture_fogintensity = NULL;
void gl_main_newmap(void)
{
// FIXME: move this code to client
- int l;
char *entities, entname[MAX_QPATH];
if (r_qwskincache)
Mem_Free(r_qwskincache);
r_qwskincache_size = 0;
if (cl.worldmodel)
{
- strlcpy(entname, cl.worldmodel->name, sizeof(entname));
- l = (int)strlen(entname) - 4;
- if (l >= 0 && !strcmp(entname + l, ".bsp"))
+ dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
+ if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
{
- memcpy(entname + l, ".ent", 5);
- if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
- {
- CL_ParseEntityLump(entities);
- Mem_Free(entities);
- return;
- }
+ CL_ParseEntityLump(entities);
+ Mem_Free(entities);
+ return;
}
if (cl.worldmodel->brush.entities)
CL_ParseEntityLump(cl.worldmodel->brush.entities);
Cvar_RegisterVariable(&r_showdisabledepthtest);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_drawentities);
+ Cvar_RegisterVariable(&r_drawworld);
Cvar_RegisterVariable(&r_cullentities_trace);
Cvar_RegisterVariable(&r_cullentities_trace_samples);
Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
Cvar_RegisterVariable(&r_cullentities_trace_delay);
Cvar_RegisterVariable(&r_drawviewmodel);
+ Cvar_RegisterVariable(&r_drawexteriormodel);
Cvar_RegisterVariable(&r_speeds);
Cvar_RegisterVariable(&r_fullbrights);
Cvar_RegisterVariable(&r_wateralpha);
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
entity_render_t *ent;
vec3_t tempdiffusenormal, avg;
vec_t f, fa, fd, fdd;
- qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
+ qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
for (i = 0;i < r_refdef.scene.numentities;i++)
{
: RENDER_EXTERIORMODEL;
if (!r_drawviewmodel.integer)
renderimask |= RENDER_VIEWMODEL;
+ if (!r_drawexteriormodel.integer)
+ renderimask |= RENDER_EXTERIORMODEL;
if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
- if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
+ if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
+ // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
{
for (i = 0;i < r_refdef.scene.numentities;i++)
{
GL_CullFace(r_refdef.view.cullface_back);
}
+/*
+================
+R_RenderView_UpdateViewVectors
+================
+*/
+static void R_RenderView_UpdateViewVectors(void)
+{
+ // break apart the view matrix into vectors for various purposes
+ // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+ // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+ VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // make an inverted copy of the view matrix for tracking sprites
+ Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+}
+
void R_RenderScene(void);
void R_RenderWaterPlanes(void);
static void R_Water_StartFrame(void)
{
int i;
- int waterwidth, waterheight, texturewidth, textureheight;
+ int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
r_waterstate_waterplane_t *p;
if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
// calculate desired texture sizes
// can't use water if the card does not support the texture size
if (!r_water.integer || r_showsurfaces.integer)
- texturewidth = textureheight = waterwidth = waterheight = 0;
+ texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
else if (vid.support.arb_texture_non_power_of_two)
{
texturewidth = waterwidth;
textureheight = waterheight;
+ camerawidth = waterwidth;
+ cameraheight = waterheight;
}
else
{
for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
+ for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
+ for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
}
// allocate textures as needed
- if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
+ if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
{
r_waterstate.maxwaterplanes = MAX_WATERPLANES;
for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
if (p->texture_reflection)
R_FreeTexture(p->texture_reflection);
p->texture_reflection = NULL;
+ if (p->texture_camera)
+ R_FreeTexture(p->texture_camera);
+ p->texture_camera = NULL;
}
memset(&r_waterstate, 0, sizeof(r_waterstate));
r_waterstate.texturewidth = texturewidth;
r_waterstate.textureheight = textureheight;
+ r_waterstate.camerawidth = camerawidth;
+ r_waterstate.cameraheight = cameraheight;
}
if (r_waterstate.texturewidth)
vec3_t normal;
vec3_t center;
mplane_t plane;
+ int cam_ent;
r_waterstate_waterplane_t *p;
texture_t *t = R_GetCurrentTexture(surface->texture);
+ cam_ent = t->camera_entity;
+ if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
+ cam_ent = 0;
+
// just use the first triangle with a valid normal for any decisions
VectorClear(normal);
for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
// find a matching plane if there is one
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
- if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
- break;
+ if(p->camera_entity == t->camera_entity)
+ if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
+ break;
if (planeindex >= r_waterstate.maxwaterplanes)
return; // nothing we can do, out of planes
// clear materialflags and pvs
p->materialflags = 0;
p->pvsvalid = false;
+ p->camera_entity = t->camera_entity;
}
// merge this surface's materialflags into the waterplane
p->materialflags |= t->currentmaterialflags;
- // merge this surface's PVS into the waterplane
- VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
- if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
- && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ if(!(p->materialflags & MATERIALFLAG_CAMERA))
{
- r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
- p->pvsvalid = true;
+ // merge this surface's PVS into the waterplane
+ VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
+ if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
+ && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
+ {
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
+ p->pvsvalid = true;
+ }
}
}
r_refdef_view_t myview;
int planeindex;
r_waterstate_waterplane_t *p;
+ vec3_t visorigin;
originalview = r_refdef.view;
if (!p->texture_refraction)
goto error;
}
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ if (!p->texture_camera)
+ p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
+ if (!p->texture_camera)
+ goto error;
+ }
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
{
r_waterstate.renderingrefraction = true;
r_refdef.view = myview;
+
r_refdef.view.clipplane = p->plane;
VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ R_RenderView_UpdateViewVectors();
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+ }
+
PlaneClassify(&r_refdef.view.clipplane);
R_ResetViewRendering3D();
R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
r_waterstate.renderingrefraction = false;
}
+ else if (p->materialflags & MATERIALFLAG_CAMERA)
+ {
+ r_refdef.view = myview;
+
+ r_refdef.view.clipplane = p->plane;
+ VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
+ r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+
+ r_refdef.view.width = r_waterstate.camerawidth;
+ r_refdef.view.height = r_waterstate.cameraheight;
+ r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
+ r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
+
+ if(p->camera_entity)
+ {
+ // we need to perform a matrix transform to render the view... so let's get the transformation matrix
+ CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
+ }
+
+ // reverse the cullface settings for this render
+ r_refdef.view.cullface_front = GL_FRONT;
+ r_refdef.view.cullface_back = GL_BACK;
+ // also reverse the view matrix
+ Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
+ R_RenderView_UpdateViewVectors();
+ if(p->camera_entity)
+ r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
+
+ // camera needs no clipplane
+ r_refdef.view.useclipplane = false;
+
+ PlaneClassify(&r_refdef.view.clipplane);
+
+ R_ResetViewRendering3D();
+ R_ClearScreen(r_refdef.fogenabled);
+ R_View_Update();
+ R_RenderScene();
+
+ R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
+ r_waterstate.renderingrefraction = false;
+ }
}
r_waterstate.renderingscene = false;
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;
return;
}
- if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
+ if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
r_refdef.view.colorscale = r_hdr_scenebrightness.value;
- // break apart the view matrix into vectors for various purposes
- // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
- // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
- Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
- VectorNegate(r_refdef.view.left, r_refdef.view.right);
- // make an inverted copy of the view matrix for tracking sprites
- Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+ R_RenderView_UpdateViewVectors();
R_Shadow_UpdateWorldLightSelection();
R_TimeReport("modeldepth");
}
- if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
+ if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadowMaps();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
if (r_refdef.scene.extraupdate)
S_ExtraUpdate ();
- if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
+ if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
{
R_DrawModelShadows();
R_ResetViewRendering3D();
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)
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)
rsurface.basepolygonfactor = r_refdef.polygonfactor;
rsurface.basepolygonoffset = r_refdef.polygonoffset;
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.generatedvertex = false;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
+ rsurface.modelvertexmesh = ent->animcache_vertexmesh;
+ rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
+ rsurface.modelvertexposition = ent->animcache_vertexposition;
+ rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
}
else if (wanttangents)
{
rsurface.modeltvector3f = rsurface.array_modeltvector3f;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else if (wantnormals)
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = rsurface.array_modelnormal3f;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
else
{
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
}
else
{
rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
- rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
rsurface.modelsvector3f = model->surfmesh.data_svector3f;
- rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
- rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
rsurface.modelnormal3f = model->surfmesh.data_normal3f;
- rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
- rsurface.generatedvertex = false;
+ rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
+ rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
+ rsurface.modelvertexposition = model->surfmesh.vertexposition;
+ rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
+ rsurface.modelgeneratedvertex = false;
}
rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
- rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
- rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
- rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
+ rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
rsurface.modelelement3s = model->surfmesh.data_element3s;
- rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
- rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
+ rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
+ rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
- rsurface.modelnum_vertices = model->surfmesh.num_vertices;
- rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelnumvertices = model->surfmesh.num_vertices;
+ rsurface.modelnumtriangles = model->surfmesh.num_triangles;
rsurface.modelsurfaces = model->data_surfaces;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
}
void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
{
+ int i;
+
rsurface.entity = r_refdef.scene.worldentity;
rsurface.skeleton = NULL;
rsurface.ent_skinnum = 0;
rsurface.ent_qwskin = -1;
rsurface.ent_shadertime = shadertime;
rsurface.ent_flags = entflags;
- rsurface.modelnum_vertices = numvertices;
- rsurface.modelnum_triangles = numtriangles;
- if (rsurface.array_size < rsurface.modelnum_vertices)
- R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
+ rsurface.modelnumvertices = numvertices;
+ rsurface.modelnumtriangles = numtriangles;
+ if (rsurface.array_size < rsurface.modelnumvertices)
+ R_Mesh_ResizeArrays(rsurface.modelnumvertices);
rsurface.matrix = *matrix;
rsurface.inversematrix = *inversematrix;
rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
rsurface.modeltvector3f = NULL;
rsurface.modelnormal3f = NULL;
}
- rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertexmesh = NULL;
+ rsurface.modelvertexmeshbuffer = NULL;
+ rsurface.modelvertexposition = NULL;
+ rsurface.modelvertexpositionbuffer = NULL;
+ rsurface.modelvertex3f_vertexbuffer = 0;
rsurface.modelvertex3f_bufferoffset = 0;
- rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_vertexbuffer = 0;
rsurface.modelsvector3f_bufferoffset = 0;
- rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_vertexbuffer = 0;
rsurface.modeltvector3f_bufferoffset = 0;
- rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_vertexbuffer = 0;
rsurface.modelnormal3f_bufferoffset = 0;
- rsurface.generatedvertex = true;
+ rsurface.modelgeneratedvertex = true;
rsurface.modellightmapcolor4f = color4f;
- rsurface.modellightmapcolor4f_bufferobject = 0;
+ rsurface.modellightmapcolor4f_vertexbuffer = 0;
rsurface.modellightmapcolor4f_bufferoffset = 0;
rsurface.modeltexcoordtexture2f = texcoord2f;
- rsurface.modeltexcoordtexture2f_bufferobject = 0;
+ rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
rsurface.modeltexcoordtexture2f_bufferoffset = 0;
rsurface.modeltexcoordlightmap2f = NULL;
- rsurface.modeltexcoordlightmap2f_bufferobject = 0;
+ rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
rsurface.modelelement3i = element3i;
+ rsurface.modelelement3i_indexbuffer = NULL;
+ rsurface.modelelement3i_bufferoffset = 0;
rsurface.modelelement3s = element3s;
- rsurface.modelelement3i_bufferobject = 0;
- rsurface.modelelement3s_bufferobject = 0;
+ rsurface.modelelement3s_indexbuffer = NULL;
+ rsurface.modelelement3s_bufferoffset = 0;
rsurface.modellightmapoffsets = NULL;
rsurface.modelsurfaces = NULL;
- rsurface.vertex3f = rsurface.modelvertex3f;
- rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
- rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
- rsurface.svector3f = rsurface.modelsvector3f;
- rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
- rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
- rsurface.tvector3f = rsurface.modeltvector3f;
- rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
- rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
- rsurface.normal3f = rsurface.modelnormal3f;
- rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
- rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
-
- if (rsurface.modelnum_vertices && rsurface.modelelement3i)
+ rsurface.batchgeneratedvertex = false;
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = 0;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = 0;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchelement3i = NULL;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ rsurface.passcolor4f = NULL;
+ rsurface.passcolor4f_vertexbuffer = NULL;
+ rsurface.passcolor4f_bufferoffset = 0;
+
+ if (rsurface.modelnumvertices && rsurface.modelelement3i)
{
if ((wantnormals || wanttangents) && !normal3f)
- Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelnormal3f = rsurface.array_modelnormal3f;
+ }
if (wanttangents && !svector3f)
- Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ {
+ Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
+ rsurface.modelsvector3f = rsurface.array_modelsvector3f;
+ rsurface.modeltvector3f = rsurface.array_modeltvector3f;
+ }
+ }
+
+ // now convert arrays into vertexmesh structs
+ for (i = 0;i < numvertices;i++)
+ {
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
+ VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
+ if (rsurface.modelsvector3f)
+ VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
+ if (rsurface.modeltvector3f)
+ VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
+ if (rsurface.modelnormal3f)
+ VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
+ if (rsurface.modellightmapcolor4f)
+ Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
+ if (rsurface.modeltexcoordtexture2f)
+ Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
+ if (rsurface.modeltexcoordlightmap2f)
+ Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
}
}
return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
}
+void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
+{
+ int i;
+ for (i = 0;i < numelements;i++)
+ outelement3i[i] = inelement3i[i] + adjust;
+}
+
static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
-void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
+extern cvar_t gl_vbo;
+void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
{
int deformindex;
- int texturesurfaceindex;
+ int firsttriangle;
+ int numtriangles;
+ int firstvertex;
+ int endvertex;
+ int numvertices;
+ int surfacefirsttriangle;
+ int surfacenumtriangles;
+ int surfacefirstvertex;
+ int surfaceendvertex;
+ int surfacenumvertices;
+ int surfaceadjustvertex;
+ int needsupdate;
int i, j;
+ qboolean gaps;
+ qboolean dynamicvertex;
float amplitude;
float animpos;
float scale;
- const float *v1, *in_tc;
- float *out_tc;
float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
float waveparms[4];
q3shaderinfo_deform_t *deform;
- // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
- if (rsurface.generatedvertex)
+ const msurface_t *surface, *firstsurface;
+ r_vertexposition_t *vertexposition;
+ r_vertexmesh_t *vertexmesh;
+ if (!texturenumsurfaces)
+ return;
+ // find vertex range of this surface batch
+ gaps = false;
+ firstsurface = texturesurfacelist[0];
+ firsttriangle = firstsurface->num_firsttriangle;
+ numtriangles = 0;
+ firstvertex = endvertex = firstsurface->num_firstvertex;
+ for (i = 0;i < texturenumsurfaces;i++)
{
- 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)
- {
- VectorClear(center);
- for (i = 0;i < 4;i++)
- VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
- VectorScale(center, 0.25f, center);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
- VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
- VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
- for (i = 0;i < 4;i++)
- {
- VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
- VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
- }
- }
- 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;
+ 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:
- 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];
- const float *v1, *v2;
- vec3_t start, end;
- float f, l;
- struct
- {
- float length2;
- const float *v1;
- const float *v2;
- }
- 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)
- {
- 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);
- // 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
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_NORMAL:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_WAVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_BULGE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
+ break;
+ case Q3DEFORM_MOVE:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
+ break;
+ }
+ }
+ switch(rsurface.texture->tcgen.tcgen)
+ {
+ default:
+ case Q3TCGEN_TEXTURE:
+ break;
+ case Q3TCGEN_LIGHTMAP:
+ batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
+ break;
+ case Q3TCGEN_VECTOR:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ case Q3TCGEN_ENVIRONMENT:
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ break;
+ }
+ if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
+ {
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
+ }
+
+ // check if any dynamic vertex processing must occur
+ dynamicvertex = false;
+
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
+ }
+
+ if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
+ {
+ dynamicvertex = true;
+ batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
+ needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
+ }
+
+ if (dynamicvertex || gaps || rsurface.batchfirstvertex)
+ {
+ // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
+ if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
+ if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
+ if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
+ if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
+ }
+
+ // when the model data has no vertex buffer (dynamic mesh), we need to
+ // eliminate gaps
+ if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
+ batchneed |= BATCHNEED_NOGAPS;
+
+ // if needsupdate, we have to do a dynamic vertex batch for sure
+ if (needsupdate & batchneed)
+ dynamicvertex = true;
+
+ // see if we need to build vertexmesh from arrays
+ if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
+ dynamicvertex = true;
+
+ // see if we need to build vertexposition from arrays
+ if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
+ dynamicvertex = true;
+
+ // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
+ if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
+ dynamicvertex = true;
+
+ // if there is a chance of animated vertex colors, it's a dynamic batch
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ dynamicvertex = true;
+
+ rsurface.batchvertex3f = rsurface.modelvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
+ rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
+ rsurface.batchsvector3f = rsurface.modelsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
+ rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
+ rsurface.batchtvector3f = rsurface.modeltvector3f;
+ rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
+ rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
+ rsurface.batchnormal3f = rsurface.modelnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
+ rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
+ rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
+ rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
+ rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
+ rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
+ rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
+ rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ rsurface.batchvertexposition = rsurface.modelvertexposition;
+ rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
+ rsurface.batchvertexmesh = rsurface.modelvertexmesh;
+ rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
+ rsurface.batchelement3i = rsurface.modelelement3i;
+ rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
+ rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
+ rsurface.batchelement3s = rsurface.modelelement3s;
+ rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
+ rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
+
+ // if any dynamic vertex processing has to occur in software, we copy the
+ // entire surface list together before processing to rebase the vertices
+ // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
+ //
+ // if any gaps exist and we do not have a static vertex buffer, we have to
+ // copy the surface list together to avoid wasting upload bandwidth on the
+ // vertices in the gaps.
+ //
+ // if gaps exist and we have a static vertex buffer, we still have to
+ // combine the index buffer ranges into one dynamic index buffer.
+ //
+ // in all cases we end up with data that can be drawn in one call.
+
+ if (!dynamicvertex)
+ {
+ // static vertex data, just set pointers...
+ rsurface.batchgeneratedvertex = false;
+ // if there are gaps, we want to build a combined index buffer,
+ // otherwise use the original static buffer with an appropriate offset
+ if (gaps)
+ {
+ firsttriangle = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
+ numtriangles += surfacenumtriangles;
+ }
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ if (endvertex <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+ rsurface.batchfirsttriangle = firsttriangle;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+ return;
+ }
+
+ // something needs software processing, do it for real...
+ // we only directly handle interleaved array data in this case...
+ rsurface.batchgeneratedvertex = true;
+
+ // now copy the vertex data into a combined array and make an index array
+ // (this is what Quake3 does all the time)
+ //if (gaps || rsurface.batchfirstvertex)
+ {
+ rsurface.batchvertexposition = NULL;
+ rsurface.batchvertexpositionbuffer = NULL;
+ rsurface.batchvertexmesh = NULL;
+ rsurface.batchvertexmeshbuffer = NULL;
+ rsurface.batchvertex3f = NULL;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = NULL;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = NULL;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = NULL;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
+ rsurface.batchlightmapcolor4f = NULL;
+ rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
+ rsurface.batchlightmapcolor4f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = NULL;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordlightmap2f = NULL;
+ rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
+ rsurface.batchelement3i = rsurface.array_batchelement3i;
+ rsurface.batchelement3i_indexbuffer = NULL;
+ rsurface.batchelement3i_bufferoffset = 0;
+ rsurface.batchelement3s = NULL;
+ rsurface.batchelement3s_indexbuffer = NULL;
+ rsurface.batchelement3s_bufferoffset = 0;
+ // we'll only be setting up certain arrays as needed
+ if (batchneed & BATCHNEED_VERTEXPOSITION)
+ rsurface.batchvertexposition = rsurface.array_batchvertexposition;
+ if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
+ rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ if (batchneed & BATCHNEED_ARRAY_NORMAL)
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ if (batchneed & BATCHNEED_ARRAY_VECTOR)
+ {
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ }
+ if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
+ rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
+ if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
+ rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
+ numvertices = 0;
+ numtriangles = 0;
+ for (i = 0;i < texturenumsurfaces;i++)
+ {
+ surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
+ surfacenumvertices = texturesurfacelist[i]->num_vertices;
+ surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
+ surfaceadjustvertex = numvertices - surfacefirstvertex;
+ surfacenumtriangles = texturesurfacelist[i]->num_triangles;
+ // copy only the data requested
+ if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
+ memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
+ memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
+ if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
+ {
+ if (batchneed & BATCHNEED_ARRAY_VERTEX)
+ memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
+ memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
+ {
+ memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
+ }
+ if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
+ memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
+ if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
+ memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
+ }
+ RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
+ numvertices += surfacenumvertices;
+ numtriangles += surfacenumtriangles;
+ }
+
+ // generate a 16bit index array as well if possible
+ // (in general, dynamic batches fit)
+ if (numvertices <= 65536)
+ {
+ rsurface.batchelement3s = rsurface.array_batchelement3s;
+ for (i = 0;i < numtriangles*3;i++)
+ rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
+ }
+
+ // since we've copied everything, the batch now starts at 0
+ rsurface.batchfirstvertex = 0;
+ rsurface.batchnumvertices = numvertices;
+ rsurface.batchfirsttriangle = 0;
+ rsurface.batchnumtriangles = numtriangles;
+ }
+
+ // q1bsp surfaces rendered in vertex color mode have to have colors
+ // calculated based on lightstyles
+ if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
+ {
+ // 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)
+ {
+ 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(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);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
+ VectorNormalize(newforward);
+ VectorNormalize(newright);
+ VectorNormalize(newup);
+ {
+ const float *v1, *v2;
+ vec3_t start, end;
+ float f, l;
+ struct
+ {
+ float length2;
+ const float *v1;
+ const float *v2;
+ }
+ shortest[2];
+ memset(shortest, 0, sizeof(shortest));
+ // 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);
+ // 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.batchvertex3f + 3*(j+quadedges[i][0]);
+ v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
l = VectorDistance2(v1, v2);
// this length bias tries to make sense of square polygons, assuming they are meant to be upright
if (v1[2] != v2[2])
}
VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
- Debug_PolygonEnd();
-#endif
// this calculates the right vector from the shortest edge
// and the up vector from the edge midpoints
VectorSubtract(shortest[0].v1, shortest[0].v2, right);
VectorNormalize(forward);
CrossProduct(up, forward, newright);
VectorNormalize(newright);
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
-#if 0
- Debug_PolygonBegin(NULL, 0);
- Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
- Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
- Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
- Debug_PolygonEnd();
-#endif
// rotate the quad around the up axis vector, this is made
// especially easy by the fact we know the quad is flat,
// so we only have to subtract the center position and
l = DotProduct(right, center);
for (i = 0;i < 4;i++)
{
- v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
+ v1 = rsurface.batchvertex3f + 3*(j+i);
f = DotProduct(right, v1) - l;
- VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+ VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
}
}
- Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_NORMAL:
// deform the normals to make reflections wavey
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- float vertex[3];
- float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
- VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
- VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
- normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
- VectorNormalize(normal);
- }
- Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
+ float vertex[3];
+ float *normal = rsurface.array_batchnormal3f + 3*j;
+ VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
+ normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
+ VectorNormalize(normal);
}
- rsurface.svector3f = rsurface.array_deformedsvector3f;
- rsurface.svector3f_bufferobject = 0;
- rsurface.svector3f_bufferoffset = 0;
- rsurface.tvector3f = rsurface.array_deformedtvector3f;
- rsurface.tvector3f_bufferobject = 0;
- rsurface.tvector3f_bufferoffset = 0;
- rsurface.normal3f = rsurface.array_deformednormal3f;
- rsurface.normal3f_bufferobject = 0;
- rsurface.normal3f_bufferoffset = 0;
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_WAVE:
// deform vertex array to make wavey water and flags and such
// this is how a divisor of vertex influence on deformation
animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
+ // if the wavefunc depends on time, evaluate it per-vertex
+ if (waveparms[3])
{
- float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
- VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
- // if the wavefunc depends on time, evaluate it per-vertex
- if (waveparms[3])
- {
- waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
- scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
- }
- VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
+ waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
+ scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
}
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_BULGE:
// deform vertex array to make the surface have moving bulges
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- {
- scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
- VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
+ scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
+ VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
}
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
+ Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
+ rsurface.batchsvector3f = rsurface.array_batchsvector3f;
+ rsurface.batchsvector3f_vertexbuffer = NULL;
+ rsurface.batchsvector3f_bufferoffset = 0;
+ rsurface.batchtvector3f = rsurface.array_batchtvector3f;
+ rsurface.batchtvector3f_vertexbuffer = NULL;
+ rsurface.batchtvector3f_bufferoffset = 0;
+ rsurface.batchnormal3f = rsurface.array_batchnormal3f;
+ rsurface.batchnormal3f_vertexbuffer = NULL;
+ rsurface.batchnormal3f_bufferoffset = 0;
break;
case Q3DEFORM_MOVE:
// deform vertex array
scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
VectorScale(deform->parms, scale, waveparms);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0;j < surface->num_vertices;j++)
- VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
- }
- rsurface.vertex3f = rsurface.array_deformedvertex3f;
- rsurface.vertex3f_bufferobject = 0;
- rsurface.vertex3f_bufferoffset = 0;
+ for (j = 0;j < rsurface.batchnumvertices;j++)
+ VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
+ rsurface.batchvertex3f = rsurface.array_batchvertex3f;
+ rsurface.batchvertex3f_vertexbuffer = NULL;
+ rsurface.batchvertex3f_bufferoffset = 0;
break;
}
}
+
// generate texcoords based on the chosen texcoord source
switch(rsurface.texture->tcgen.tcgen)
{
default:
case Q3TCGEN_TEXTURE:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
break;
case Q3TCGEN_LIGHTMAP:
- rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
+ if (rsurface.batchtexcoordlightmap2f)
+ memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_VECTOR:
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
- {
- out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
- out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
case Q3TCGEN_ENVIRONMENT:
// make environment reflections using a spheremap
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
- const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
- float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
- for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
- {
- // identical to Q3A's method, but executed in worldspace so
- // carried models can be shiny too
+ // identical to Q3A's method, but executed in worldspace so
+ // carried models can be shiny too
- float viewer[3], d, reflected[3], worldreflected[3];
+ float viewer[3], d, reflected[3], worldreflected[3];
- VectorSubtract(rsurface.localvieworigin, vertex, viewer);
- // VectorNormalize(viewer);
+ VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
+ // VectorNormalize(viewer);
- d = DotProduct(normal, viewer);
+ d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
- reflected[0] = normal[0]*2*d - viewer[0];
- reflected[1] = normal[1]*2*d - viewer[1];
- reflected[2] = normal[2]*2*d - viewer[2];
- // note: this is proportinal to viewer, so we can normalize later
+ reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
+ reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
+ reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
+ // note: this is proportinal to viewer, so we can normalize later
- Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
- VectorNormalize(worldreflected);
+ Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
+ VectorNormalize(worldreflected);
- // note: this sphere map only uses world x and z!
- // so positive and negative y will LOOK THE SAME.
- out_tc[0] = 0.5 + 0.5 * worldreflected[1];
- out_tc[1] = 0.5 - 0.5 * worldreflected[2];
- }
+ // note: this sphere map only uses world x and z!
+ // so positive and negative y will LOOK THE SAME.
+ rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
+ rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
break;
}
// the only tcmod that needs software vertex processing is turbulent, so
{
amplitude = rsurface.texture->tcmods[0].parms[1];
animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (j = 0;j < rsurface.batchnumvertices;j++)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
- {
- out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
- }
+ rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
+ rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
}
- rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
- rsurface.texcoordtexture2f_bufferobject = 0;
- rsurface.texcoordtexture2f_bufferoffset = 0;
+ rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
+ rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
+ rsurface.batchtexcoordtexture2f_bufferoffset = 0;
}
- rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
- rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
- rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
- R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
-}
-void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- int i, j;
- const msurface_t *surface = texturesurfacelist[0];
- const msurface_t *surface2;
- int firstvertex;
- int endvertex;
- int numvertices;
- int numtriangles;
- // TODO: lock all array ranges before render, rather than on each surface
- if (texturenumsurfaces == 1)
- 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 65536
- 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)
+ for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
{
- 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 (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);
}
+ 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 (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);
- }
- }
- 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)
-{
- 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);
- }
-}
-
-static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
-{
- 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)
- {
- 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)
+static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
{
- 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;
+ 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_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
+static void RSurf_DrawBatch_GL11_ApplyFog(void)
{
- 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);
- if(!rsurface.lightmapcolor4f)
- RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
+ rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
+ rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
+ rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
+ }
- 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);
+ if(!rsurface.passcolor4f)
+ RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
- R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
- RSurf_DrawBatch_Simple(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_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)
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 + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
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
{
// (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);
}
}
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);
brush = model->brush.data_brushes + bihleaf->itemindex;
if (brush->colbrushf && brush->colbrushf->numtriangles)
{
- R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
+ 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:
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
- R_Mesh_VertexPointer(vertex3f[0], 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ 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]);
- R_Mesh_VertexPointer(vertex3f[0], 0, 0);
GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
- R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
+ 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;
// 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);
}