2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 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"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
83 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
84 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
85 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
87 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
88 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
89 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
90 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
91 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
92 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
93 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
95 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
96 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
97 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
98 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
100 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
102 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
104 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
106 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
107 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
109 extern qboolean v_flipped_state;
111 typedef struct r_glsl_bloomshader_s
114 int loc_Texture_Bloom;
116 r_glsl_bloomshader_t;
118 static struct r_bloomstate_s
123 int bloomwidth, bloomheight;
125 int screentexturewidth, screentextureheight;
126 rtexture_t *texture_screen;
128 int bloomtexturewidth, bloomtextureheight;
129 rtexture_t *texture_bloom;
131 r_glsl_bloomshader_t *shader;
133 // arrays for rendering the screen passes
134 float screentexcoord2f[8];
135 float bloomtexcoord2f[8];
136 float offsettexcoord2f[8];
140 // shadow volume bsp struct with automatically growing nodes buffer
143 rtexture_t *r_texture_blanknormalmap;
144 rtexture_t *r_texture_white;
145 rtexture_t *r_texture_black;
146 rtexture_t *r_texture_notexture;
147 rtexture_t *r_texture_whitecube;
148 rtexture_t *r_texture_normalizationcube;
149 rtexture_t *r_texture_fogattenuation;
150 //rtexture_t *r_texture_fogintensity;
152 // information about each possible shader permutation
153 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
154 // currently selected permutation
155 r_glsl_permutation_t *r_glsl_permutation;
157 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
158 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
160 // vertex coordinates for a quad that covers the screen exactly
161 const static float r_screenvertex3f[12] =
169 extern void R_DrawModelShadows(void);
171 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
174 for (i = 0;i < verts;i++)
185 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
188 for (i = 0;i < verts;i++)
198 // FIXME: move this to client?
201 if (gamemode == GAME_NEHAHRA)
203 Cvar_Set("gl_fogenable", "0");
204 Cvar_Set("gl_fogdensity", "0.2");
205 Cvar_Set("gl_fogred", "0.3");
206 Cvar_Set("gl_foggreen", "0.3");
207 Cvar_Set("gl_fogblue", "0.3");
209 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
212 float FogPoint_World(const vec3_t p)
214 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
215 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
218 float FogPoint_Model(const vec3_t p)
220 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
221 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
224 static void R_BuildBlankTextures(void)
226 unsigned char data[4];
227 data[0] = 128; // normal X
228 data[1] = 128; // normal Y
229 data[2] = 255; // normal Z
230 data[3] = 128; // height
231 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
236 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
241 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
244 static void R_BuildNoTexture(void)
247 unsigned char pix[16][16][4];
248 // this makes a light grey/dark grey checkerboard texture
249 for (y = 0;y < 16;y++)
251 for (x = 0;x < 16;x++)
253 if ((y < 8) ^ (x < 8))
269 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
272 static void R_BuildWhiteCube(void)
274 unsigned char data[6*1*1*4];
275 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
276 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
277 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
278 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
279 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
280 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
281 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
284 static void R_BuildNormalizationCube(void)
288 vec_t s, t, intensity;
290 unsigned char data[6][NORMSIZE][NORMSIZE][4];
291 for (side = 0;side < 6;side++)
293 for (y = 0;y < NORMSIZE;y++)
295 for (x = 0;x < NORMSIZE;x++)
297 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
298 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
333 intensity = 127.0f / sqrt(DotProduct(v, v));
334 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
335 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
336 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
337 data[side][y][x][3] = 255;
341 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
344 static void R_BuildFogTexture(void)
348 unsigned char data1[FOGWIDTH][4];
349 //unsigned char data2[FOGWIDTH][4];
350 for (x = 0;x < FOGWIDTH;x++)
352 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
357 //data2[x][0] = 255 - b;
358 //data2[x][1] = 255 - b;
359 //data2[x][2] = 255 - b;
362 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
363 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
366 static const char *builtinshaderstring =
367 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
368 "// written by Forest 'LordHavoc' Hale\n"
370 "// common definitions between vertex shader and fragment shader:\n"
372 "#ifdef __GLSL_CG_DATA_TYPES\n"
373 "#define myhalf half\n"
374 "#define myhvec2 hvec2\n"
375 "#define myhvec3 hvec3\n"
376 "#define myhvec4 hvec4\n"
378 "#define myhalf float\n"
379 "#define myhvec2 vec2\n"
380 "#define myhvec3 vec3\n"
381 "#define myhvec4 vec4\n"
384 "varying vec2 TexCoord;\n"
385 "varying vec2 TexCoordLightmap;\n"
387 "varying vec3 CubeVector;\n"
388 "varying vec3 LightVector;\n"
389 "varying vec3 EyeVector;\n"
391 "varying vec3 EyeVectorModelSpace;\n"
394 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
395 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
396 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
401 "// vertex shader specific:\n"
402 "#ifdef VERTEX_SHADER\n"
404 "uniform vec3 LightPosition;\n"
405 "uniform vec3 EyePosition;\n"
406 "uniform vec3 LightDir;\n"
408 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
412 " gl_FrontColor = gl_Color;\n"
413 " // copy the surface texcoord\n"
414 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
415 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
416 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
419 "#ifdef MODE_LIGHTSOURCE\n"
420 " // transform vertex position into light attenuation/cubemap space\n"
421 " // (-1 to +1 across the light box)\n"
422 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
424 " // transform unnormalized light direction into tangent space\n"
425 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
426 " // normalize it per pixel)\n"
427 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
428 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
429 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
430 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
433 "#ifdef MODE_LIGHTDIRECTION\n"
434 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
435 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
436 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
439 " // transform unnormalized eye direction into tangent space\n"
441 " vec3 EyeVectorModelSpace;\n"
443 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
444 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
445 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
446 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
448 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
449 " VectorS = gl_MultiTexCoord1.xyz;\n"
450 " VectorT = gl_MultiTexCoord2.xyz;\n"
451 " VectorR = gl_MultiTexCoord3.xyz;\n"
454 " // transform vertex to camera space, using ftransform to match non-VS\n"
456 " gl_Position = ftransform();\n"
459 "#endif // VERTEX_SHADER\n"
464 "// fragment shader specific:\n"
465 "#ifdef FRAGMENT_SHADER\n"
467 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
468 "uniform sampler2D Texture_Normal;\n"
469 "uniform sampler2D Texture_Color;\n"
470 "uniform sampler2D Texture_Gloss;\n"
471 "uniform samplerCube Texture_Cube;\n"
472 "uniform sampler2D Texture_Attenuation;\n"
473 "uniform sampler2D Texture_FogMask;\n"
474 "uniform sampler2D Texture_Pants;\n"
475 "uniform sampler2D Texture_Shirt;\n"
476 "uniform sampler2D Texture_Lightmap;\n"
477 "uniform sampler2D Texture_Deluxemap;\n"
478 "uniform sampler2D Texture_Glow;\n"
480 "uniform myhvec3 LightColor;\n"
481 "uniform myhvec3 AmbientColor;\n"
482 "uniform myhvec3 DiffuseColor;\n"
483 "uniform myhvec3 SpecularColor;\n"
484 "uniform myhvec3 Color_Pants;\n"
485 "uniform myhvec3 Color_Shirt;\n"
486 "uniform myhvec3 FogColor;\n"
488 "uniform myhalf GlowScale;\n"
489 "uniform myhalf SceneBrightness;\n"
491 "uniform float OffsetMapping_Scale;\n"
492 "uniform float OffsetMapping_Bias;\n"
493 "uniform float FogRangeRecip;\n"
495 "uniform myhalf AmbientScale;\n"
496 "uniform myhalf DiffuseScale;\n"
497 "uniform myhalf SpecularScale;\n"
498 "uniform myhalf SpecularPower;\n"
500 "#ifdef USEOFFSETMAPPING\n"
501 "vec2 OffsetMapping(vec2 TexCoord)\n"
503 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
504 " // 14 sample relief mapping: linear search and then binary search\n"
505 " // this basically steps forward a small amount repeatedly until it finds\n"
506 " // itself inside solid, then jitters forward and back using decreasing\n"
507 " // amounts to find the impact\n"
508 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
509 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
510 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
511 " vec3 RT = vec3(TexCoord, 1);\n"
512 " OffsetVector *= 0.1;\n"
513 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
514 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
515 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
516 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
517 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
518 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
519 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
520 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
521 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
522 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
523 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
524 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
525 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
526 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
529 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
530 " // this basically moves forward the full distance, and then backs up based\n"
531 " // on height of samples\n"
532 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
533 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
534 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
535 " TexCoord += OffsetVector;\n"
536 " OffsetVector *= 0.333;\n"
537 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
538 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
539 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
540 " return TexCoord;\n"
547 "#ifdef USEOFFSETMAPPING\n"
548 " // apply offsetmapping\n"
549 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
550 "#define TexCoord TexCoordOffset\n"
553 " // combine the diffuse textures (base, pants, shirt)\n"
554 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
555 "#ifdef USECOLORMAPPING\n"
556 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
562 "#ifdef MODE_LIGHTSOURCE\n"
565 " // calculate surface normal, light normal, and specular normal\n"
566 " // compute color intensity for the two textures (colormap and glossmap)\n"
567 " // scale by light color and attenuation as efficiently as possible\n"
568 " // (do as much scalar math as possible rather than vector math)\n"
569 "#ifdef USESPECULAR\n"
570 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
571 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
572 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
574 " // calculate directional shading\n"
575 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
577 "#ifdef USEDIFFUSE\n"
578 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
579 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
581 " // calculate directional shading\n"
582 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
584 " // calculate directionless shading\n"
585 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
589 "#ifdef USECUBEFILTER\n"
590 " // apply light cubemap filter\n"
591 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
592 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
598 "#elif defined(MODE_LIGHTDIRECTION)\n"
599 " // directional model lighting\n"
601 " // get the surface normal and light normal\n"
602 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
603 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
605 " // calculate directional shading\n"
606 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
607 "#ifdef USESPECULAR\n"
608 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
609 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
615 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
616 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
618 " // get the surface normal and light normal\n"
619 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
621 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
622 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
623 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
625 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
627 " // calculate directional shading\n"
628 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
629 "#ifdef USESPECULAR\n"
630 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
631 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
634 " // apply lightmap color\n"
635 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
638 "#else // MODE none (lightmap)\n"
639 " // apply lightmap color\n"
640 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
643 " color *= myhvec4(gl_Color);\n"
646 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
651 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
654 " color.rgb *= SceneBrightness;\n"
656 " gl_FragColor = vec4(color);\n"
659 "#endif // FRAGMENT_SHADER\n"
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 const char *permutationinfo[][2] =
665 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
666 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
667 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
668 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
669 {"#define USEGLOW\n", " glow"},
670 {"#define USEFOG\n", " fog"},
671 {"#define USECOLORMAPPING\n", " colormapping"},
672 {"#define USEDIFFUSE\n", " diffuse"},
673 {"#define USESPECULAR\n", " specular"},
674 {"#define USECUBEFILTER\n", " cubefilter"},
675 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
676 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
680 void R_GLSL_CompilePermutation(const char *filename, int permutation)
683 qboolean shaderfound;
684 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
685 int vertstrings_count;
686 int geomstrings_count;
687 int fragstrings_count;
689 const char *vertstrings_list[32+1];
690 const char *geomstrings_list[32+1];
691 const char *fragstrings_list[32+1];
692 char permutationname[256];
697 vertstrings_list[0] = "#define VERTEX_SHADER\n";
698 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
699 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
700 vertstrings_count = 1;
701 geomstrings_count = 1;
702 fragstrings_count = 1;
703 permutationname[0] = 0;
704 for (i = 0;permutationinfo[i][0];i++)
706 if (permutation & (1<<i))
708 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
709 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
710 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
711 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
715 // keep line numbers correct
716 vertstrings_list[vertstrings_count++] = "\n";
717 geomstrings_list[geomstrings_count++] = "\n";
718 fragstrings_list[fragstrings_count++] = "\n";
721 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
725 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
726 vertstrings_list[vertstrings_count++] = shaderstring;
727 geomstrings_list[geomstrings_count++] = shaderstring;
728 fragstrings_list[fragstrings_count++] = shaderstring;
731 else if (!strcmp(filename, "glsl/default.glsl"))
733 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
734 vertstrings_list[vertstrings_count++] = builtinshaderstring;
735 geomstrings_list[geomstrings_count++] = builtinshaderstring;
736 fragstrings_list[fragstrings_count++] = builtinshaderstring;
739 // clear any lists that are not needed by this shader
740 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
741 vertstrings_count = 0;
742 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
743 geomstrings_count = 0;
744 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
745 fragstrings_count = 0;
746 // compile the shader program
747 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
748 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
752 qglUseProgramObjectARB(p->program);CHECKGLERROR
753 // look up all the uniform variable names we care about, so we don't
754 // have to look them up every time we set them
755 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
756 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
757 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
758 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
759 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
760 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
761 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
762 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
763 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
764 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
765 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
766 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
767 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
768 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
769 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
770 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
771 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
772 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
773 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
774 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
775 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
776 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
777 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
778 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
779 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
780 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
781 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
782 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
783 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
784 // initialize the samplers to refer to the texture units we use
785 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
786 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
787 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
788 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
789 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
790 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
791 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
792 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
793 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
794 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
795 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
797 qglUseProgramObjectARB(0);CHECKGLERROR
800 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
802 Mem_Free(shaderstring);
805 void R_GLSL_Restart_f(void)
808 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
809 if (r_glsl_permutations[i].program)
810 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
811 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
814 extern rtexture_t *r_shadow_attenuationgradienttexture;
815 extern rtexture_t *r_shadow_attenuation2dtexture;
816 extern rtexture_t *r_shadow_attenuation3dtexture;
817 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
819 // select a permutation of the lighting shader appropriate to this
820 // combination of texture, entity, light source, and fogging, only use the
821 // minimum features necessary to avoid wasting rendering time in the
822 // fragment shader on features that are not being used
823 const char *shaderfilename = NULL;
824 unsigned int permutation = 0;
825 r_glsl_permutation = NULL;
826 // TODO: implement geometry-shader based shadow volumes someday
827 if (rsurface.rtlight)
830 shaderfilename = "glsl/default.glsl";
831 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
832 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
833 permutation |= SHADERPERMUTATION_CUBEFILTER;
834 if (diffusescale > 0)
835 permutation |= SHADERPERMUTATION_DIFFUSE;
836 if (specularscale > 0)
837 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
838 if (r_refdef.fogenabled)
839 permutation |= SHADERPERMUTATION_FOG;
840 if (rsurface.texture->colormapping)
841 permutation |= SHADERPERMUTATION_COLORMAPPING;
842 if (r_glsl_offsetmapping.integer)
844 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
845 if (r_glsl_offsetmapping_reliefmapping.integer)
846 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
849 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
851 // bright unshaded geometry
852 shaderfilename = "glsl/default.glsl";
853 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
854 if (rsurface.texture->currentskinframe->glow)
855 permutation |= SHADERPERMUTATION_GLOW;
856 if (r_refdef.fogenabled)
857 permutation |= SHADERPERMUTATION_FOG;
858 if (rsurface.texture->colormapping)
859 permutation |= SHADERPERMUTATION_COLORMAPPING;
860 if (r_glsl_offsetmapping.integer)
862 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
863 if (r_glsl_offsetmapping_reliefmapping.integer)
864 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
867 else if (modellighting)
869 // directional model lighting
870 shaderfilename = "glsl/default.glsl";
871 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
872 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
873 if (rsurface.texture->currentskinframe->glow)
874 permutation |= SHADERPERMUTATION_GLOW;
875 if (specularscale > 0)
876 permutation |= SHADERPERMUTATION_SPECULAR;
877 if (r_refdef.fogenabled)
878 permutation |= SHADERPERMUTATION_FOG;
879 if (rsurface.texture->colormapping)
880 permutation |= SHADERPERMUTATION_COLORMAPPING;
881 if (r_glsl_offsetmapping.integer)
883 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
884 if (r_glsl_offsetmapping_reliefmapping.integer)
885 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
891 shaderfilename = "glsl/default.glsl";
892 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
893 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
895 // deluxemapping (light direction texture)
896 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
897 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
899 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
900 if (specularscale > 0)
901 permutation |= SHADERPERMUTATION_SPECULAR;
903 else if (r_glsl_deluxemapping.integer >= 2)
905 // fake deluxemapping (uniform light direction in tangentspace)
906 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
907 if (specularscale > 0)
908 permutation |= SHADERPERMUTATION_SPECULAR;
912 // ordinary lightmapping
915 if (rsurface.texture->currentskinframe->glow)
916 permutation |= SHADERPERMUTATION_GLOW;
917 if (r_refdef.fogenabled)
918 permutation |= SHADERPERMUTATION_FOG;
919 if (rsurface.texture->colormapping)
920 permutation |= SHADERPERMUTATION_COLORMAPPING;
921 if (r_glsl_offsetmapping.integer)
923 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
924 if (r_glsl_offsetmapping_reliefmapping.integer)
925 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
928 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
930 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
931 R_GLSL_CompilePermutation(shaderfilename, permutation);
932 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
934 // remove features until we find a valid permutation
936 for (i = SHADERPERMUTATION_MASK;;i>>=1)
939 return 0; // utterly failed
940 // reduce i more quickly whenever it would not remove any bits
944 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
945 R_GLSL_CompilePermutation(shaderfilename, permutation);
946 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
951 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
953 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
954 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
955 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
957 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
958 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
959 if (permutation & SHADERPERMUTATION_DIFFUSE)
961 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
962 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
963 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
964 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
968 // ambient only is simpler
969 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
970 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
971 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
972 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
975 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
977 if (r_glsl_permutation->loc_AmbientColor >= 0)
978 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
979 if (r_glsl_permutation->loc_DiffuseColor >= 0)
980 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
981 if (r_glsl_permutation->loc_SpecularColor >= 0)
982 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
983 if (r_glsl_permutation->loc_LightDir >= 0)
984 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
988 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
989 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
990 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
992 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
993 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
994 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
995 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
996 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
997 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
998 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
999 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1000 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1001 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1002 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1003 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1004 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1005 if (r_glsl_permutation->loc_FogColor >= 0)
1007 // additive passes are only darkened by fog, not tinted
1008 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1009 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1011 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1013 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1014 if (r_glsl_permutation->loc_Color_Pants >= 0)
1016 if (rsurface.texture->currentskinframe->pants)
1017 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1019 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1021 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1023 if (rsurface.texture->currentskinframe->shirt)
1024 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1026 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1028 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1029 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1030 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1035 void R_SwitchSurfaceShader(int permutation)
1037 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1039 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1041 qglUseProgramObjectARB(r_glsl_permutation->program);
1046 #define SKINFRAME_HASH 1024
1050 int loadsequence; // incremented each level change
1051 memexpandablearray_t array;
1052 skinframe_t *hash[SKINFRAME_HASH];
1056 void R_SkinFrame_PrepareForPurge(void)
1058 r_skinframe.loadsequence++;
1059 // wrap it without hitting zero
1060 if (r_skinframe.loadsequence >= 200)
1061 r_skinframe.loadsequence = 1;
1064 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1068 // mark the skinframe as used for the purging code
1069 skinframe->loadsequence = r_skinframe.loadsequence;
1072 void R_SkinFrame_Purge(void)
1076 for (i = 0;i < SKINFRAME_HASH;i++)
1078 for (s = r_skinframe.hash[i];s;s = s->next)
1080 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1082 if (s->base == r_texture_notexture) s->base = NULL;
1083 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1084 if (s->merged == s->base) s->merged = NULL;
1085 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1086 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1087 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1088 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1089 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1090 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1091 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1092 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1093 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1094 s->loadsequence = 0;
1100 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1104 char basename[MAX_QPATH];
1106 Image_StripImageExtension(name, basename, sizeof(basename));
1108 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1109 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1110 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1116 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1117 memset(item, 0, sizeof(*item));
1118 strlcpy(item->basename, basename, sizeof(item->basename));
1119 item->textureflags = textureflags;
1120 item->comparewidth = comparewidth;
1121 item->compareheight = compareheight;
1122 item->comparecrc = comparecrc;
1123 item->next = r_skinframe.hash[hashindex];
1124 r_skinframe.hash[hashindex] = item;
1126 R_SkinFrame_MarkUsed(item);
1130 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1132 // FIXME: it should be possible to disable loading various layers using
1133 // cvars, to prevent wasted loading time and memory usage if the user does
1135 qboolean loadnormalmap = true;
1136 qboolean loadgloss = true;
1137 qboolean loadpantsandshirt = true;
1138 qboolean loadglow = true;
1140 unsigned char *pixels;
1141 unsigned char *bumppixels;
1142 unsigned char *basepixels = NULL;
1143 int basepixels_width;
1144 int basepixels_height;
1145 skinframe_t *skinframe;
1147 if (cls.state == ca_dedicated)
1150 // return an existing skinframe if already loaded
1151 // if loading of the first image fails, don't make a new skinframe as it
1152 // would cause all future lookups of this to be missing
1153 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1154 if (skinframe && skinframe->base)
1157 basepixels = loadimagepixels(name, complain, 0, 0);
1158 if (basepixels == NULL)
1161 // we've got some pixels to store, so really allocate this new texture now
1163 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1164 skinframe->stain = NULL;
1165 skinframe->merged = NULL;
1166 skinframe->base = r_texture_notexture;
1167 skinframe->pants = NULL;
1168 skinframe->shirt = NULL;
1169 skinframe->nmap = r_texture_blanknormalmap;
1170 skinframe->gloss = NULL;
1171 skinframe->glow = NULL;
1172 skinframe->fog = NULL;
1174 basepixels_width = image_width;
1175 basepixels_height = image_height;
1176 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1178 if (textureflags & TEXF_ALPHA)
1180 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1181 if (basepixels[j] < 255)
1183 if (j < basepixels_width * basepixels_height * 4)
1185 // has transparent pixels
1186 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1187 for (j = 0;j < image_width * image_height * 4;j += 4)
1192 pixels[j+3] = basepixels[j+3];
1194 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1199 // _norm is the name used by tenebrae and has been adopted as standard
1202 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1204 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1208 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1210 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1211 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1212 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1214 Mem_Free(bumppixels);
1216 else if (r_shadow_bumpscale_basetexture.value > 0)
1218 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1219 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1220 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1224 // _luma is supported for tenebrae compatibility
1225 // (I think it's a very stupid name, but oh well)
1226 // _glow is the preferred name
1227 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1228 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1229 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1230 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1233 Mem_Free(basepixels);
1238 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1243 for (i = 0;i < width*height;i++)
1244 if (((unsigned char *)&palette[in[i]])[3] > 0)
1246 if (i == width*height)
1249 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1252 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1255 unsigned char *temp1, *temp2;
1256 skinframe_t *skinframe;
1258 if (cls.state == ca_dedicated)
1261 // if already loaded just return it, otherwise make a new skinframe
1262 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1263 if (skinframe && skinframe->base)
1266 skinframe->stain = NULL;
1267 skinframe->merged = NULL;
1268 skinframe->base = r_texture_notexture;
1269 skinframe->pants = NULL;
1270 skinframe->shirt = NULL;
1271 skinframe->nmap = r_texture_blanknormalmap;
1272 skinframe->gloss = NULL;
1273 skinframe->glow = NULL;
1274 skinframe->fog = NULL;
1276 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1280 if (bitsperpixel == 32)
1282 if (r_shadow_bumpscale_basetexture.value > 0)
1284 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1285 temp2 = temp1 + width * height * 4;
1286 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1287 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1290 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1291 if (textureflags & TEXF_ALPHA)
1293 for (i = 3;i < width * height * 4;i += 4)
1294 if (skindata[i] < 255)
1296 if (i < width * height * 4)
1298 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1299 memcpy(fogpixels, skindata, width * height * 4);
1300 for (i = 0;i < width * height * 4;i += 4)
1301 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1302 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1303 Mem_Free(fogpixels);
1307 else if (bitsperpixel == 8)
1309 if (r_shadow_bumpscale_basetexture.value > 0)
1311 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1312 temp2 = temp1 + width * height * 4;
1313 if (bitsperpixel == 32)
1314 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1317 // use either a custom palette or the quake palette
1318 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1319 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1321 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1324 // use either a custom palette, or the quake palette
1325 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
1326 if (!palette && loadglowtexture)
1327 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1328 if (!palette && loadpantsandshirt)
1330 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1331 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1333 if (skinframe->pants || skinframe->shirt)
1334 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1335 if (textureflags & TEXF_ALPHA)
1337 // if not using a custom alphapalette, use the quake one
1339 alphapalette = palette_alpha;
1340 for (i = 0;i < width * height;i++)
1341 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1343 if (i < width * height)
1344 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1351 skinframe_t *R_SkinFrame_LoadMissing(void)
1353 skinframe_t *skinframe;
1355 if (cls.state == ca_dedicated)
1358 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1359 skinframe->stain = NULL;
1360 skinframe->merged = NULL;
1361 skinframe->base = r_texture_notexture;
1362 skinframe->pants = NULL;
1363 skinframe->shirt = NULL;
1364 skinframe->nmap = r_texture_blanknormalmap;
1365 skinframe->gloss = NULL;
1366 skinframe->glow = NULL;
1367 skinframe->fog = NULL;
1372 void gl_main_start(void)
1377 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1378 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1380 alpha = 1 - exp(r / ((double)x*(double)x));
1381 if (x == FOGMASKTABLEWIDTH - 1)
1383 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1386 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1387 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1389 // set up r_skinframe loading system for textures
1390 memset(&r_skinframe, 0, sizeof(r_skinframe));
1391 r_skinframe.loadsequence = 1;
1392 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1394 r_main_texturepool = R_AllocTexturePool();
1395 R_BuildBlankTextures();
1397 if (gl_texturecubemap)
1400 R_BuildNormalizationCube();
1402 R_BuildFogTexture();
1403 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1404 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1405 memset(&r_svbsp, 0, sizeof (r_svbsp));
1408 void gl_main_shutdown(void)
1410 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1411 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1413 // clear out the r_skinframe state
1414 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1415 memset(&r_skinframe, 0, sizeof(r_skinframe));
1418 Mem_Free(r_svbsp.nodes);
1419 memset(&r_svbsp, 0, sizeof (r_svbsp));
1420 R_FreeTexturePool(&r_main_texturepool);
1421 r_texture_blanknormalmap = NULL;
1422 r_texture_white = NULL;
1423 r_texture_black = NULL;
1424 r_texture_whitecube = NULL;
1425 r_texture_normalizationcube = NULL;
1426 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1430 extern void CL_ParseEntityLump(char *entitystring);
1431 void gl_main_newmap(void)
1433 // FIXME: move this code to client
1435 char *entities, entname[MAX_QPATH];
1438 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1439 l = (int)strlen(entname) - 4;
1440 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1442 memcpy(entname + l, ".ent", 5);
1443 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1445 CL_ParseEntityLump(entities);
1450 if (cl.worldmodel->brush.entities)
1451 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1455 void GL_Main_Init(void)
1457 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1459 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1460 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1461 if (gamemode == GAME_NEHAHRA)
1463 Cvar_RegisterVariable (&gl_fogenable);
1464 Cvar_RegisterVariable (&gl_fogdensity);
1465 Cvar_RegisterVariable (&gl_fogred);
1466 Cvar_RegisterVariable (&gl_foggreen);
1467 Cvar_RegisterVariable (&gl_fogblue);
1468 Cvar_RegisterVariable (&gl_fogstart);
1469 Cvar_RegisterVariable (&gl_fogend);
1471 Cvar_RegisterVariable(&r_depthfirst);
1472 Cvar_RegisterVariable(&r_nearclip);
1473 Cvar_RegisterVariable(&r_showbboxes);
1474 Cvar_RegisterVariable(&r_showsurfaces);
1475 Cvar_RegisterVariable(&r_showtris);
1476 Cvar_RegisterVariable(&r_shownormals);
1477 Cvar_RegisterVariable(&r_showlighting);
1478 Cvar_RegisterVariable(&r_showshadowvolumes);
1479 Cvar_RegisterVariable(&r_showcollisionbrushes);
1480 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1481 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1482 Cvar_RegisterVariable(&r_showdisabledepthtest);
1483 Cvar_RegisterVariable(&r_drawportals);
1484 Cvar_RegisterVariable(&r_drawentities);
1485 Cvar_RegisterVariable(&r_cullentities_trace);
1486 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1487 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1488 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1489 Cvar_RegisterVariable(&r_drawviewmodel);
1490 Cvar_RegisterVariable(&r_speeds);
1491 Cvar_RegisterVariable(&r_fullbrights);
1492 Cvar_RegisterVariable(&r_wateralpha);
1493 Cvar_RegisterVariable(&r_dynamic);
1494 Cvar_RegisterVariable(&r_fullbright);
1495 Cvar_RegisterVariable(&r_shadows);
1496 Cvar_RegisterVariable(&r_shadows_throwdistance);
1497 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1498 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1499 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1500 Cvar_RegisterVariable(&r_textureunits);
1501 Cvar_RegisterVariable(&r_glsl);
1502 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1503 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1504 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1505 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1506 Cvar_RegisterVariable(&r_lerpsprites);
1507 Cvar_RegisterVariable(&r_lerpmodels);
1508 Cvar_RegisterVariable(&r_waterscroll);
1509 Cvar_RegisterVariable(&r_bloom);
1510 Cvar_RegisterVariable(&r_bloom_colorscale);
1511 Cvar_RegisterVariable(&r_bloom_brighten);
1512 Cvar_RegisterVariable(&r_bloom_blur);
1513 Cvar_RegisterVariable(&r_bloom_resolution);
1514 Cvar_RegisterVariable(&r_bloom_colorexponent);
1515 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1516 Cvar_RegisterVariable(&r_hdr);
1517 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1518 Cvar_RegisterVariable(&r_hdr_glowintensity);
1519 Cvar_RegisterVariable(&r_hdr_range);
1520 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1521 Cvar_RegisterVariable(&developer_texturelogging);
1522 Cvar_RegisterVariable(&gl_lightmaps);
1523 Cvar_RegisterVariable(&r_test);
1524 Cvar_RegisterVariable(&r_batchmode);
1525 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1526 Cvar_SetValue("r_fullbrights", 0);
1527 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1530 extern void R_Textures_Init(void);
1531 extern void GL_Draw_Init(void);
1532 extern void GL_Main_Init(void);
1533 extern void R_Shadow_Init(void);
1534 extern void R_Sky_Init(void);
1535 extern void GL_Surf_Init(void);
1536 extern void R_Light_Init(void);
1537 extern void R_Particles_Init(void);
1538 extern void R_Explosion_Init(void);
1539 extern void gl_backend_init(void);
1540 extern void Sbar_Init(void);
1541 extern void R_LightningBeams_Init(void);
1542 extern void Mod_RenderInit(void);
1544 void Render_Init(void)
1557 R_LightningBeams_Init();
1566 extern char *ENGINE_EXTENSIONS;
1569 VID_CheckExtensions();
1571 // LordHavoc: report supported extensions
1572 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1574 // clear to black (loading plaque will be seen over this)
1576 qglClearColor(0,0,0,1);CHECKGLERROR
1577 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1580 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1584 for (i = 0;i < 4;i++)
1586 p = r_view.frustum + i;
1591 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1595 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1599 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1603 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1607 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1611 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1615 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1619 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1627 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1631 for (i = 0;i < numplanes;i++)
1638 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1642 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1646 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1650 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1654 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1658 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1662 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1666 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1674 //==================================================================================
1676 static void R_UpdateEntityLighting(entity_render_t *ent)
1678 vec3_t tempdiffusenormal;
1680 // fetch the lighting from the worldmodel data
1681 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1682 VectorClear(ent->modellight_diffuse);
1683 VectorClear(tempdiffusenormal);
1684 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1687 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1688 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1691 VectorSet(ent->modellight_ambient, 1, 1, 1);
1693 // move the light direction into modelspace coordinates for lighting code
1694 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1695 if(VectorLength2(ent->modellight_lightdir) > 0)
1697 VectorNormalize(ent->modellight_lightdir);
1701 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1704 // scale ambient and directional light contributions according to rendering variables
1705 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1706 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1707 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1708 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1709 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1710 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1713 static void R_View_UpdateEntityVisible (void)
1716 entity_render_t *ent;
1718 if (!r_drawentities.integer)
1721 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1722 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1724 // worldmodel can check visibility
1725 for (i = 0;i < r_refdef.numentities;i++)
1727 ent = r_refdef.entities[i];
1728 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1730 if(r_cullentities_trace.integer)
1732 for (i = 0;i < r_refdef.numentities;i++)
1734 ent = r_refdef.entities[i];
1735 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1737 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1738 ent->last_trace_visibility = realtime;
1739 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1740 r_viewcache.entityvisible[i] = 0;
1747 // no worldmodel or it can't check visibility
1748 for (i = 0;i < r_refdef.numentities;i++)
1750 ent = r_refdef.entities[i];
1751 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1755 // update entity lighting (even on hidden entities for r_shadows)
1756 for (i = 0;i < r_refdef.numentities;i++)
1757 R_UpdateEntityLighting(r_refdef.entities[i]);
1760 // only used if skyrendermasked, and normally returns false
1761 int R_DrawBrushModelsSky (void)
1764 entity_render_t *ent;
1766 if (!r_drawentities.integer)
1770 for (i = 0;i < r_refdef.numentities;i++)
1772 if (!r_viewcache.entityvisible[i])
1774 ent = r_refdef.entities[i];
1775 if (!ent->model || !ent->model->DrawSky)
1777 ent->model->DrawSky(ent);
1783 void R_DrawNoModel(entity_render_t *ent);
1784 void R_DrawModels(void)
1787 entity_render_t *ent;
1789 if (!r_drawentities.integer)
1792 for (i = 0;i < r_refdef.numentities;i++)
1794 if (!r_viewcache.entityvisible[i])
1796 ent = r_refdef.entities[i];
1797 r_refdef.stats.entities++;
1798 if (ent->model && ent->model->Draw != NULL)
1799 ent->model->Draw(ent);
1805 void R_DrawModelsDepth(void)
1808 entity_render_t *ent;
1810 if (!r_drawentities.integer)
1813 for (i = 0;i < r_refdef.numentities;i++)
1815 if (!r_viewcache.entityvisible[i])
1817 ent = r_refdef.entities[i];
1818 r_refdef.stats.entities++;
1819 if (ent->model && ent->model->DrawDepth != NULL)
1820 ent->model->DrawDepth(ent);
1824 static void R_View_SetFrustum(void)
1826 double slopex, slopey;
1828 // break apart the view matrix into vectors for various purposes
1829 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1830 VectorNegate(r_view.left, r_view.right);
1833 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1834 r_view.frustum[0].normal[1] = 0 - 0;
1835 r_view.frustum[0].normal[2] = -1 - 0;
1836 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1837 r_view.frustum[1].normal[1] = 0 + 0;
1838 r_view.frustum[1].normal[2] = -1 + 0;
1839 r_view.frustum[2].normal[0] = 0 - 0;
1840 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1841 r_view.frustum[2].normal[2] = -1 - 0;
1842 r_view.frustum[3].normal[0] = 0 + 0;
1843 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1844 r_view.frustum[3].normal[2] = -1 + 0;
1848 zNear = r_refdef.nearclip;
1849 nudge = 1.0 - 1.0 / (1<<23);
1850 r_view.frustum[4].normal[0] = 0 - 0;
1851 r_view.frustum[4].normal[1] = 0 - 0;
1852 r_view.frustum[4].normal[2] = -1 - -nudge;
1853 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1854 r_view.frustum[5].normal[0] = 0 + 0;
1855 r_view.frustum[5].normal[1] = 0 + 0;
1856 r_view.frustum[5].normal[2] = -1 + -nudge;
1857 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1863 r_view.frustum[0].normal[0] = m[3] - m[0];
1864 r_view.frustum[0].normal[1] = m[7] - m[4];
1865 r_view.frustum[0].normal[2] = m[11] - m[8];
1866 r_view.frustum[0].dist = m[15] - m[12];
1868 r_view.frustum[1].normal[0] = m[3] + m[0];
1869 r_view.frustum[1].normal[1] = m[7] + m[4];
1870 r_view.frustum[1].normal[2] = m[11] + m[8];
1871 r_view.frustum[1].dist = m[15] + m[12];
1873 r_view.frustum[2].normal[0] = m[3] - m[1];
1874 r_view.frustum[2].normal[1] = m[7] - m[5];
1875 r_view.frustum[2].normal[2] = m[11] - m[9];
1876 r_view.frustum[2].dist = m[15] - m[13];
1878 r_view.frustum[3].normal[0] = m[3] + m[1];
1879 r_view.frustum[3].normal[1] = m[7] + m[5];
1880 r_view.frustum[3].normal[2] = m[11] + m[9];
1881 r_view.frustum[3].dist = m[15] + m[13];
1883 r_view.frustum[4].normal[0] = m[3] - m[2];
1884 r_view.frustum[4].normal[1] = m[7] - m[6];
1885 r_view.frustum[4].normal[2] = m[11] - m[10];
1886 r_view.frustum[4].dist = m[15] - m[14];
1888 r_view.frustum[5].normal[0] = m[3] + m[2];
1889 r_view.frustum[5].normal[1] = m[7] + m[6];
1890 r_view.frustum[5].normal[2] = m[11] + m[10];
1891 r_view.frustum[5].dist = m[15] + m[14];
1896 slopex = 1.0 / r_view.frustum_x;
1897 slopey = 1.0 / r_view.frustum_y;
1898 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1899 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1900 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1901 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1902 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1903 VectorNormalize(r_view.frustum[0].normal);
1904 VectorNormalize(r_view.frustum[1].normal);
1905 VectorNormalize(r_view.frustum[2].normal);
1906 VectorNormalize(r_view.frustum[3].normal);
1907 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1908 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1909 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1910 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1911 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1912 PlaneClassify(&r_view.frustum[0]);
1913 PlaneClassify(&r_view.frustum[1]);
1914 PlaneClassify(&r_view.frustum[2]);
1915 PlaneClassify(&r_view.frustum[3]);
1916 PlaneClassify(&r_view.frustum[4]);
1918 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1919 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1920 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1921 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1922 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1924 // LordHavoc: note to all quake engine coders, Quake had a special case
1925 // for 90 degrees which assumed a square view (wrong), so I removed it,
1926 // Quake2 has it disabled as well.
1928 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1929 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1930 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1931 //PlaneClassify(&frustum[0]);
1933 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1934 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1935 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1936 //PlaneClassify(&frustum[1]);
1938 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1939 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1940 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1941 //PlaneClassify(&frustum[2]);
1943 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1944 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1945 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1946 //PlaneClassify(&frustum[3]);
1949 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1950 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1951 //PlaneClassify(&frustum[4]);
1954 void R_View_Update(void)
1956 R_View_SetFrustum();
1957 R_View_WorldVisibility();
1958 R_View_UpdateEntityVisible();
1961 void R_SetupView(const matrix4x4_t *matrix)
1963 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1964 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1966 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1968 GL_SetupView_Orientation_FromEntity(matrix);
1971 void R_ResetViewRendering2D(void)
1973 if (gl_support_fragment_shader)
1975 qglUseProgramObjectARB(0);CHECKGLERROR
1980 // GL is weird because it's bottom to top, r_view.y is top to bottom
1981 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1982 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1983 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1984 GL_Color(1, 1, 1, 1);
1985 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1986 GL_BlendFunc(GL_ONE, GL_ZERO);
1987 GL_AlphaTest(false);
1988 GL_ScissorTest(false);
1989 GL_DepthMask(false);
1990 GL_DepthRange(0, 1);
1991 GL_DepthTest(false);
1992 R_Mesh_Matrix(&identitymatrix);
1993 R_Mesh_ResetTextureState();
1994 GL_PolygonOffset(0, 0);
1995 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1996 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1997 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1998 qglStencilMask(~0);CHECKGLERROR
1999 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2000 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2001 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2004 void R_ResetViewRendering3D(void)
2006 if (gl_support_fragment_shader)
2008 qglUseProgramObjectARB(0);CHECKGLERROR
2013 // GL is weird because it's bottom to top, r_view.y is top to bottom
2014 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2015 R_SetupView(&r_view.matrix);
2016 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2017 GL_Color(1, 1, 1, 1);
2018 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2019 GL_BlendFunc(GL_ONE, GL_ZERO);
2020 GL_AlphaTest(false);
2021 GL_ScissorTest(true);
2023 GL_DepthRange(0, 1);
2025 R_Mesh_Matrix(&identitymatrix);
2026 R_Mesh_ResetTextureState();
2027 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2028 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2029 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2030 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2031 qglStencilMask(~0);CHECKGLERROR
2032 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2033 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2034 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2038 R_Bloom_SetupShader(
2040 "// written by Forest 'LordHavoc' Hale\n"
2042 "// common definitions between vertex shader and fragment shader:\n"
2044 "#ifdef __GLSL_CG_DATA_TYPES\n"
2045 "#define myhalf half\n"
2046 "#define myhvec2 hvec2\n"
2047 "#define myhvec3 hvec3\n"
2048 "#define myhvec4 hvec4\n"
2050 "#define myhalf float\n"
2051 "#define myhvec2 vec2\n"
2052 "#define myhvec3 vec3\n"
2053 "#define myhvec4 vec4\n"
2056 "varying vec2 ScreenTexCoord;\n"
2057 "varying vec2 BloomTexCoord;\n"
2062 "// vertex shader specific:\n"
2063 "#ifdef VERTEX_SHADER\n"
2067 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2068 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2069 " // transform vertex to camera space, using ftransform to match non-VS\n"
2071 " gl_Position = ftransform();\n"
2074 "#endif // VERTEX_SHADER\n"
2079 "// fragment shader specific:\n"
2080 "#ifdef FRAGMENT_SHADER\n"
2085 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2086 " for (x = -BLUR_X;x <= BLUR_X;x++)
2087 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2088 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2089 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2090 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2092 " gl_FragColor = vec4(color);\n"
2095 "#endif // FRAGMENT_SHADER\n"
2098 void R_RenderScene(void);
2100 void R_Bloom_StartFrame(void)
2102 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2104 // set bloomwidth and bloomheight to the bloom resolution that will be
2105 // used (often less than the screen resolution for faster rendering)
2106 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2107 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2108 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2110 // calculate desired texture sizes
2111 if (gl_support_arb_texture_non_power_of_two)
2113 screentexturewidth = r_view.width;
2114 screentextureheight = r_view.height;
2115 bloomtexturewidth = r_bloomstate.bloomwidth;
2116 bloomtextureheight = r_bloomstate.bloomheight;
2120 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2121 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2122 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2123 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2128 screentexturewidth = screentextureheight = 0;
2130 else if (r_bloom.integer)
2135 screentexturewidth = screentextureheight = 0;
2136 bloomtexturewidth = bloomtextureheight = 0;
2139 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
2141 // can't use bloom if the parameters are too weird
2142 // can't use bloom if the card does not support the texture size
2143 if (r_bloomstate.texture_screen)
2144 R_FreeTexture(r_bloomstate.texture_screen);
2145 if (r_bloomstate.texture_bloom)
2146 R_FreeTexture(r_bloomstate.texture_bloom);
2147 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2151 r_bloomstate.enabled = true;
2152 r_bloomstate.hdr = r_hdr.integer != 0;
2154 // allocate textures as needed
2155 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2157 if (r_bloomstate.texture_screen)
2158 R_FreeTexture(r_bloomstate.texture_screen);
2159 r_bloomstate.texture_screen = NULL;
2160 r_bloomstate.screentexturewidth = screentexturewidth;
2161 r_bloomstate.screentextureheight = screentextureheight;
2162 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2163 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2165 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2167 if (r_bloomstate.texture_bloom)
2168 R_FreeTexture(r_bloomstate.texture_bloom);
2169 r_bloomstate.texture_bloom = NULL;
2170 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2171 r_bloomstate.bloomtextureheight = bloomtextureheight;
2172 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2173 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2176 // set up a texcoord array for the full resolution screen image
2177 // (we have to keep this around to copy back during final render)
2178 r_bloomstate.screentexcoord2f[0] = 0;
2179 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2180 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2181 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2182 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2183 r_bloomstate.screentexcoord2f[5] = 0;
2184 r_bloomstate.screentexcoord2f[6] = 0;
2185 r_bloomstate.screentexcoord2f[7] = 0;
2187 // set up a texcoord array for the reduced resolution bloom image
2188 // (which will be additive blended over the screen image)
2189 r_bloomstate.bloomtexcoord2f[0] = 0;
2190 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2191 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2192 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2193 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2194 r_bloomstate.bloomtexcoord2f[5] = 0;
2195 r_bloomstate.bloomtexcoord2f[6] = 0;
2196 r_bloomstate.bloomtexcoord2f[7] = 0;
2199 void R_Bloom_CopyScreenTexture(float colorscale)
2201 r_refdef.stats.bloom++;
2203 R_ResetViewRendering2D();
2204 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2205 R_Mesh_ColorPointer(NULL, 0, 0);
2206 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2207 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2209 // copy view into the screen texture
2210 GL_ActiveTexture(0);
2212 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2213 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2215 // now scale it down to the bloom texture size
2217 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2218 GL_BlendFunc(GL_ONE, GL_ZERO);
2219 GL_Color(colorscale, colorscale, colorscale, 1);
2220 // TODO: optimize with multitexture or GLSL
2221 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2222 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2224 // we now have a bloom image in the framebuffer
2225 // copy it into the bloom image texture for later processing
2226 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2227 GL_ActiveTexture(0);
2229 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2230 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2233 void R_Bloom_CopyHDRTexture(void)
2235 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2236 GL_ActiveTexture(0);
2238 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2239 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2242 void R_Bloom_MakeTexture(void)
2245 float xoffset, yoffset, r, brighten;
2247 r_refdef.stats.bloom++;
2249 R_ResetViewRendering2D();
2250 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2251 R_Mesh_ColorPointer(NULL, 0, 0);
2253 // we have a bloom image in the framebuffer
2255 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2257 for (x = 1;x < r_bloom_colorexponent.value;)
2260 r = bound(0, r_bloom_colorexponent.value / x, 1);
2261 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2262 GL_Color(r, r, r, 1);
2263 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2264 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2265 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2266 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2268 // copy the vertically blurred bloom view to a texture
2269 GL_ActiveTexture(0);
2271 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2272 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2275 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2276 brighten = r_bloom_brighten.value;
2278 brighten *= r_hdr_range.value;
2279 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2280 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2282 for (dir = 0;dir < 2;dir++)
2284 // blend on at multiple vertical offsets to achieve a vertical blur
2285 // TODO: do offset blends using GLSL
2286 GL_BlendFunc(GL_ONE, GL_ZERO);
2287 for (x = -range;x <= range;x++)
2289 if (!dir){xoffset = 0;yoffset = x;}
2290 else {xoffset = x;yoffset = 0;}
2291 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2292 yoffset /= (float)r_bloomstate.bloomtextureheight;
2293 // compute a texcoord array with the specified x and y offset
2294 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2295 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2296 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2297 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2298 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2299 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2300 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2301 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2302 // this r value looks like a 'dot' particle, fading sharply to
2303 // black at the edges
2304 // (probably not realistic but looks good enough)
2305 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2306 //r = (dir ? 1.0f : brighten)/(range*2+1);
2307 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2308 GL_Color(r, r, r, 1);
2309 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2310 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2311 GL_BlendFunc(GL_ONE, GL_ONE);
2314 // copy the vertically blurred bloom view to a texture
2315 GL_ActiveTexture(0);
2317 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2318 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2321 // apply subtract last
2322 // (just like it would be in a GLSL shader)
2323 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2325 GL_BlendFunc(GL_ONE, GL_ZERO);
2326 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2327 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2328 GL_Color(1, 1, 1, 1);
2329 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2330 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2332 GL_BlendFunc(GL_ONE, GL_ONE);
2333 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2334 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2335 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2336 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2337 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2338 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2339 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2341 // copy the darkened bloom view to a texture
2342 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2343 GL_ActiveTexture(0);
2345 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2346 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2350 void R_HDR_RenderBloomTexture(void)
2352 int oldwidth, oldheight;
2354 oldwidth = r_view.width;
2355 oldheight = r_view.height;
2356 r_view.width = r_bloomstate.bloomwidth;
2357 r_view.height = r_bloomstate.bloomheight;
2359 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2360 // TODO: add exposure compensation features
2361 // TODO: add fp16 framebuffer support
2363 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2365 r_view.colorscale /= r_hdr_range.value;
2368 R_ResetViewRendering2D();
2370 R_Bloom_CopyHDRTexture();
2371 R_Bloom_MakeTexture();
2373 R_ResetViewRendering3D();
2376 if (r_timereport_active)
2377 R_TimeReport("clear");
2380 // restore the view settings
2381 r_view.width = oldwidth;
2382 r_view.height = oldheight;
2385 static void R_BlendView(void)
2387 if (r_bloomstate.enabled && r_bloomstate.hdr)
2389 // render high dynamic range bloom effect
2390 // the bloom texture was made earlier this render, so we just need to
2391 // blend it onto the screen...
2392 R_ResetViewRendering2D();
2393 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2394 R_Mesh_ColorPointer(NULL, 0, 0);
2395 GL_Color(1, 1, 1, 1);
2396 GL_BlendFunc(GL_ONE, GL_ONE);
2397 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2398 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2399 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2400 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2402 else if (r_bloomstate.enabled)
2404 // render simple bloom effect
2405 // copy the screen and shrink it and darken it for the bloom process
2406 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2407 // make the bloom texture
2408 R_Bloom_MakeTexture();
2409 // put the original screen image back in place and blend the bloom
2411 R_ResetViewRendering2D();
2412 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2413 R_Mesh_ColorPointer(NULL, 0, 0);
2414 GL_Color(1, 1, 1, 1);
2415 GL_BlendFunc(GL_ONE, GL_ZERO);
2416 // do both in one pass if possible
2417 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2418 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2419 if (r_textureunits.integer >= 2 && gl_combine.integer)
2421 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2422 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2423 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2427 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2428 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2429 // now blend on the bloom texture
2430 GL_BlendFunc(GL_ONE, GL_ONE);
2431 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2432 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2434 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2435 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2437 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2439 // apply a color tint to the whole view
2440 R_ResetViewRendering2D();
2441 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2442 R_Mesh_ColorPointer(NULL, 0, 0);
2443 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2444 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2445 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2449 void R_RenderScene(void);
2451 matrix4x4_t r_waterscrollmatrix;
2453 void R_UpdateVariables(void)
2457 r_refdef.farclip = 4096;
2458 if (r_refdef.worldmodel)
2459 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2460 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2462 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2463 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2464 r_refdef.polygonfactor = 0;
2465 r_refdef.polygonoffset = 0;
2466 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2467 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2469 r_refdef.rtworld = r_shadow_realtime_world.integer;
2470 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2471 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2472 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2473 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2474 if (r_showsurfaces.integer)
2476 r_refdef.rtworld = false;
2477 r_refdef.rtworldshadows = false;
2478 r_refdef.rtdlight = false;
2479 r_refdef.rtdlightshadows = false;
2480 r_refdef.lightmapintensity = 0;
2483 if (gamemode == GAME_NEHAHRA)
2485 if (gl_fogenable.integer)
2487 r_refdef.oldgl_fogenable = true;
2488 r_refdef.fog_density = gl_fogdensity.value;
2489 r_refdef.fog_red = gl_fogred.value;
2490 r_refdef.fog_green = gl_foggreen.value;
2491 r_refdef.fog_blue = gl_fogblue.value;
2493 else if (r_refdef.oldgl_fogenable)
2495 r_refdef.oldgl_fogenable = false;
2496 r_refdef.fog_density = 0;
2497 r_refdef.fog_red = 0;
2498 r_refdef.fog_green = 0;
2499 r_refdef.fog_blue = 0;
2502 if (r_refdef.fog_density)
2504 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2505 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2506 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2508 if (r_refdef.fog_density)
2510 r_refdef.fogenabled = true;
2511 // this is the point where the fog reaches 0.9986 alpha, which we
2512 // consider a good enough cutoff point for the texture
2513 // (0.9986 * 256 == 255.6)
2514 r_refdef.fogrange = 400 / r_refdef.fog_density;
2515 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2516 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2517 // fog color was already set
2520 r_refdef.fogenabled = false;
2528 void R_RenderView(void)
2530 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2531 return; //Host_Error ("R_RenderView: NULL worldmodel");
2533 R_Shadow_UpdateWorldLightSelection();
2536 if (r_timereport_active)
2537 R_TimeReport("setup");
2540 if (r_timereport_active)
2541 R_TimeReport("visibility");
2543 R_ResetViewRendering3D();
2546 if (r_timereport_active)
2547 R_TimeReport("clear");
2549 R_Bloom_StartFrame();
2551 // this produces a bloom texture to be used in R_BlendView() later
2553 R_HDR_RenderBloomTexture();
2555 r_view.colorscale = r_hdr_scenebrightness.value;
2559 if (r_timereport_active)
2560 R_TimeReport("blendview");
2562 GL_Scissor(0, 0, vid.width, vid.height);
2563 GL_ScissorTest(false);
2567 extern void R_DrawLightningBeams (void);
2568 extern void VM_CL_AddPolygonsToMeshQueue (void);
2569 extern void R_DrawPortals (void);
2570 extern cvar_t cl_locs_show;
2571 static void R_DrawLocs(void);
2572 static void R_DrawEntityBBoxes(void);
2573 void R_RenderScene(void)
2575 // don't let sound skip if going slow
2576 if (r_refdef.extraupdate)
2579 R_ResetViewRendering3D();
2581 R_MeshQueue_BeginScene();
2585 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
2587 if (cl.csqc_vidvars.drawworld)
2589 // don't let sound skip if going slow
2590 if (r_refdef.extraupdate)
2593 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2595 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2596 if (r_timereport_active)
2597 R_TimeReport("worldsky");
2600 if (R_DrawBrushModelsSky() && r_timereport_active)
2601 R_TimeReport("bmodelsky");
2604 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2606 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2607 if (r_timereport_active)
2608 R_TimeReport("worlddepth");
2610 if (r_depthfirst.integer >= 2)
2612 R_DrawModelsDepth();
2613 if (r_timereport_active)
2614 R_TimeReport("modeldepth");
2617 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2619 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2620 if (r_timereport_active)
2621 R_TimeReport("world");
2624 // don't let sound skip if going slow
2625 if (r_refdef.extraupdate)
2629 if (r_timereport_active)
2630 R_TimeReport("models");
2632 // don't let sound skip if going slow
2633 if (r_refdef.extraupdate)
2636 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2638 R_DrawModelShadows();
2640 R_ResetViewRendering3D();
2642 // don't let sound skip if going slow
2643 if (r_refdef.extraupdate)
2647 R_ShadowVolumeLighting(false);
2648 if (r_timereport_active)
2649 R_TimeReport("rtlights");
2651 // don't let sound skip if going slow
2652 if (r_refdef.extraupdate)
2655 if (cl.csqc_vidvars.drawworld)
2657 R_DrawLightningBeams();
2658 if (r_timereport_active)
2659 R_TimeReport("lightning");
2662 if (r_timereport_active)
2663 R_TimeReport("particles");
2666 if (r_timereport_active)
2667 R_TimeReport("explosions");
2670 if (gl_support_fragment_shader)
2672 qglUseProgramObjectARB(0);CHECKGLERROR
2674 VM_CL_AddPolygonsToMeshQueue();
2676 if (cl_locs_show.integer)
2679 if (r_timereport_active)
2680 R_TimeReport("showlocs");
2683 if (r_drawportals.integer)
2686 if (r_timereport_active)
2687 R_TimeReport("portals");
2690 if (r_showbboxes.value > 0)
2692 R_DrawEntityBBoxes();
2693 if (r_timereport_active)
2694 R_TimeReport("bboxes");
2697 if (gl_support_fragment_shader)
2699 qglUseProgramObjectARB(0);CHECKGLERROR
2701 R_MeshQueue_RenderTransparent();
2702 if (r_timereport_active)
2703 R_TimeReport("drawtrans");
2705 if (gl_support_fragment_shader)
2707 qglUseProgramObjectARB(0);CHECKGLERROR
2710 if (cl.csqc_vidvars.drawworld)
2713 if (r_timereport_active)
2714 R_TimeReport("coronas");
2717 // don't let sound skip if going slow
2718 if (r_refdef.extraupdate)
2721 R_ResetViewRendering2D();
2724 static const int bboxelements[36] =
2734 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2737 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2738 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2739 GL_DepthMask(false);
2740 GL_DepthRange(0, 1);
2741 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2742 R_Mesh_Matrix(&identitymatrix);
2743 R_Mesh_ResetTextureState();
2745 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2746 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2747 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2748 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2749 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2750 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2751 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2752 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2753 R_FillColors(color4f, 8, cr, cg, cb, ca);
2754 if (r_refdef.fogenabled)
2756 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2758 f1 = FogPoint_World(v);
2760 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2761 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2762 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2765 R_Mesh_VertexPointer(vertex3f, 0, 0);
2766 R_Mesh_ColorPointer(color4f, 0, 0);
2767 R_Mesh_ResetTextureState();
2768 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2771 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2775 prvm_edict_t *edict;
2776 // this function draws bounding boxes of server entities
2780 for (i = 0;i < numsurfaces;i++)
2782 edict = PRVM_EDICT_NUM(surfacelist[i]);
2783 switch ((int)edict->fields.server->solid)
2785 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2786 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2787 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2788 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2789 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2790 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2792 color[3] *= r_showbboxes.value;
2793 color[3] = bound(0, color[3], 1);
2794 GL_DepthTest(!r_showdisabledepthtest.integer);
2795 GL_CullFace(GL_BACK);
2796 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2801 static void R_DrawEntityBBoxes(void)
2804 prvm_edict_t *edict;
2806 // this function draws bounding boxes of server entities
2810 for (i = 0;i < prog->num_edicts;i++)
2812 edict = PRVM_EDICT_NUM(i);
2813 if (edict->priv.server->free)
2815 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2816 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2821 int nomodelelements[24] =
2833 float nomodelvertex3f[6*3] =
2843 float nomodelcolor4f[6*4] =
2845 0.0f, 0.0f, 0.5f, 1.0f,
2846 0.0f, 0.0f, 0.5f, 1.0f,
2847 0.0f, 0.5f, 0.0f, 1.0f,
2848 0.0f, 0.5f, 0.0f, 1.0f,
2849 0.5f, 0.0f, 0.0f, 1.0f,
2850 0.5f, 0.0f, 0.0f, 1.0f
2853 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2858 // this is only called once per entity so numsurfaces is always 1, and
2859 // surfacelist is always {0}, so this code does not handle batches
2860 R_Mesh_Matrix(&ent->matrix);
2862 if (ent->flags & EF_ADDITIVE)
2864 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2865 GL_DepthMask(false);
2867 else if (ent->alpha < 1)
2869 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2870 GL_DepthMask(false);
2874 GL_BlendFunc(GL_ONE, GL_ZERO);
2877 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2878 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2879 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2880 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2881 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2882 if (r_refdef.fogenabled)
2885 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2886 R_Mesh_ColorPointer(color4f, 0, 0);
2887 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2888 f1 = FogPoint_World(org);
2890 for (i = 0, c = color4f;i < 6;i++, c += 4)
2892 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2893 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2894 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2898 else if (ent->alpha != 1)
2900 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2901 R_Mesh_ColorPointer(color4f, 0, 0);
2902 for (i = 0, c = color4f;i < 6;i++, c += 4)
2906 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2907 R_Mesh_ResetTextureState();
2908 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2911 void R_DrawNoModel(entity_render_t *ent)
2914 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2915 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2916 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2918 // R_DrawNoModelCallback(ent, 0);
2921 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2923 vec3_t right1, right2, diff, normal;
2925 VectorSubtract (org2, org1, normal);
2927 // calculate 'right' vector for start
2928 VectorSubtract (r_view.origin, org1, diff);
2929 CrossProduct (normal, diff, right1);
2930 VectorNormalize (right1);
2932 // calculate 'right' vector for end
2933 VectorSubtract (r_view.origin, org2, diff);
2934 CrossProduct (normal, diff, right2);
2935 VectorNormalize (right2);
2937 vert[ 0] = org1[0] + width * right1[0];
2938 vert[ 1] = org1[1] + width * right1[1];
2939 vert[ 2] = org1[2] + width * right1[2];
2940 vert[ 3] = org1[0] - width * right1[0];
2941 vert[ 4] = org1[1] - width * right1[1];
2942 vert[ 5] = org1[2] - width * right1[2];
2943 vert[ 6] = org2[0] - width * right2[0];
2944 vert[ 7] = org2[1] - width * right2[1];
2945 vert[ 8] = org2[2] - width * right2[2];
2946 vert[ 9] = org2[0] + width * right2[0];
2947 vert[10] = org2[1] + width * right2[1];
2948 vert[11] = org2[2] + width * right2[2];
2951 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2953 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
2958 if (r_refdef.fogenabled)
2959 fog = FogPoint_World(origin);
2961 R_Mesh_Matrix(&identitymatrix);
2962 GL_BlendFunc(blendfunc1, blendfunc2);
2968 GL_CullFace(GL_BACK);
2971 GL_CullFace(GL_FRONT);
2973 GL_DepthMask(false);
2974 GL_DepthRange(0, depthshort ? 0.0625 : 1);
2975 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2976 GL_DepthTest(!depthdisable);
2978 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2979 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2980 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2981 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2982 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2983 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2984 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2985 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2986 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2987 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2988 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2989 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2991 R_Mesh_VertexPointer(vertex3f, 0, 0);
2992 R_Mesh_ColorPointer(NULL, 0, 0);
2993 R_Mesh_ResetTextureState();
2994 R_Mesh_TexBind(0, R_GetTexture(texture));
2995 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2996 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2997 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2998 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3000 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3002 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3003 GL_BlendFunc(blendfunc1, GL_ONE);
3005 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
3006 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3010 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3015 VectorSet(v, x, y, z);
3016 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3017 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3019 if (i == mesh->numvertices)
3021 if (mesh->numvertices < mesh->maxvertices)
3023 VectorCopy(v, vertex3f);
3024 mesh->numvertices++;
3026 return mesh->numvertices;
3032 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3036 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3037 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3038 e = mesh->element3i + mesh->numtriangles * 3;
3039 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3041 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3042 if (mesh->numtriangles < mesh->maxtriangles)
3047 mesh->numtriangles++;
3049 element[1] = element[2];
3053 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3057 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3058 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3059 e = mesh->element3i + mesh->numtriangles * 3;
3060 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3062 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3063 if (mesh->numtriangles < mesh->maxtriangles)
3068 mesh->numtriangles++;
3070 element[1] = element[2];
3074 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3075 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3077 int planenum, planenum2;
3080 mplane_t *plane, *plane2;
3082 double temppoints[2][256*3];
3083 // figure out how large a bounding box we need to properly compute this brush
3085 for (w = 0;w < numplanes;w++)
3086 maxdist = max(maxdist, planes[w].dist);
3087 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3088 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3089 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3093 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3094 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3096 if (planenum2 == planenum)
3098 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
3101 if (tempnumpoints < 3)
3103 // generate elements forming a triangle fan for this polygon
3104 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3108 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3111 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3112 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3113 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3114 GL_LockArrays(0, brush->numpoints);
3115 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3116 GL_LockArrays(0, 0);
3119 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3122 if (!surface->num_collisiontriangles)
3124 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3125 i = (int)(((size_t)surface) / sizeof(msurface_t));
3126 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3127 GL_LockArrays(0, surface->num_collisionvertices);
3128 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3129 GL_LockArrays(0, 0);
3132 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
3134 texturelayer_t *layer;
3135 layer = t->currentlayers + t->currentnumlayers++;
3137 layer->depthmask = depthmask;
3138 layer->blendfunc1 = blendfunc1;
3139 layer->blendfunc2 = blendfunc2;
3140 layer->texture = texture;
3141 layer->texmatrix = *matrix;
3142 layer->color[0] = r * r_view.colorscale;
3143 layer->color[1] = g * r_view.colorscale;
3144 layer->color[2] = b * r_view.colorscale;
3145 layer->color[3] = a;
3148 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3151 index = parms[2] + r_refdef.time * parms[3];
3152 index -= floor(index);
3156 case Q3WAVEFUNC_NONE:
3157 case Q3WAVEFUNC_NOISE:
3158 case Q3WAVEFUNC_COUNT:
3161 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3162 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3163 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3164 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3165 case Q3WAVEFUNC_TRIANGLE:
3167 f = index - floor(index);
3178 return (float)(parms[0] + parms[1] * f);
3181 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3184 model_t *model = ent->model;
3187 q3shaderinfo_layer_tcmod_t *tcmod;
3189 // switch to an alternate material if this is a q1bsp animated material
3191 texture_t *texture = t;
3192 int s = ent->skinnum;
3193 if ((unsigned int)s >= (unsigned int)model->numskins)
3195 if (model->skinscenes)
3197 if (model->skinscenes[s].framecount > 1)
3198 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3200 s = model->skinscenes[s].firstframe;
3203 t = t + s * model->num_surfaces;
3206 // use an alternate animation if the entity's frame is not 0,
3207 // and only if the texture has an alternate animation
3208 if (ent->frame != 0 && t->anim_total[1])
3209 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3211 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3213 texture->currentframe = t;
3216 // update currentskinframe to be a qw skin or animation frame
3217 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3219 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3221 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3222 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3223 r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, developer.integer > 0);
3225 t->currentskinframe = r_qwskincache_skinframe[i];
3226 if (t->currentskinframe == NULL)
3227 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3229 else if (t->numskinframes >= 2)
3230 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3231 if (t->backgroundnumskinframes >= 2)
3232 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3234 t->currentmaterialflags = t->basematerialflags;
3235 t->currentalpha = ent->alpha;
3236 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3237 t->currentalpha *= r_wateralpha.value;
3238 if (!(ent->flags & RENDER_LIGHT))
3239 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3240 if (ent->effects & EF_ADDITIVE)
3241 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3242 else if (t->currentalpha < 1)
3243 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3244 if (ent->effects & EF_DOUBLESIDED)
3245 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3246 if (ent->effects & EF_NODEPTHTEST)
3247 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3248 if (ent->flags & RENDER_VIEWMODEL)
3249 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3250 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3251 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3253 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3256 switch(tcmod->tcmod)
3260 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3261 matrix = r_waterscrollmatrix;
3263 matrix = identitymatrix;
3265 case Q3TCMOD_ENTITYTRANSLATE:
3266 // this is used in Q3 to allow the gamecode to control texcoord
3267 // scrolling on the entity, which is not supported in darkplaces yet.
3268 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3270 case Q3TCMOD_ROTATE:
3271 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3272 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3273 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3276 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3278 case Q3TCMOD_SCROLL:
3279 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3281 case Q3TCMOD_STRETCH:
3282 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3283 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3285 case Q3TCMOD_TRANSFORM:
3286 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3287 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3288 VectorSet(tcmat + 6, 0 , 0 , 1);
3289 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3290 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3292 case Q3TCMOD_TURBULENT:
3293 // this is handled in the RSurf_PrepareVertices function
3294 matrix = identitymatrix;
3297 // either replace or concatenate the transformation
3299 t->currenttexmatrix = matrix;
3302 matrix4x4_t temp = t->currenttexmatrix;
3303 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3307 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3308 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3309 t->glosstexture = r_texture_white;
3310 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3311 t->backgroundglosstexture = r_texture_white;
3312 t->specularpower = r_shadow_glossexponent.value;
3313 // TODO: store reference values for these in the texture?
3314 t->specularscale = 0;
3315 if (r_shadow_gloss.integer > 0)
3317 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3319 if (r_shadow_glossintensity.value > 0)
3321 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3322 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3323 t->specularscale = r_shadow_glossintensity.value;
3326 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3327 t->specularscale = r_shadow_gloss2intensity.value;
3330 t->currentpolygonfactor = r_refdef.polygonfactor;
3331 t->currentpolygonoffset = r_refdef.polygonoffset;
3332 // submodels are biased to avoid z-fighting with world surfaces that they
3333 // may be exactly overlapping (avoids z-fighting artifacts on certain
3334 // doors and things in Quake maps)
3335 if (ent->model->brush.submodel)
3337 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3338 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3341 VectorClear(t->dlightcolor);
3342 t->currentnumlayers = 0;
3343 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3345 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3347 int blendfunc1, blendfunc2, depthmask;
3348 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3350 blendfunc1 = GL_SRC_ALPHA;
3351 blendfunc2 = GL_ONE;
3353 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3355 blendfunc1 = GL_SRC_ALPHA;
3356 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3358 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3360 blendfunc1 = t->customblendfunc[0];
3361 blendfunc2 = t->customblendfunc[1];
3365 blendfunc1 = GL_ONE;
3366 blendfunc2 = GL_ZERO;
3368 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3369 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3371 rtexture_t *currentbasetexture;
3373 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3374 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3375 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3376 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3378 // fullbright is not affected by r_refdef.lightmapintensity
3379 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3380 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3381 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
3382 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3383 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
3388 // set the color tint used for lights affecting this surface
3389 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3391 // q3bsp has no lightmap updates, so the lightstylevalue that
3392 // would normally be baked into the lightmap must be
3393 // applied to the color
3394 if (ent->model->type == mod_brushq3)
3395 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3396 colorscale *= r_refdef.lightmapintensity;
3397 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
3398 if (r_ambient.value >= (1.0f/64.0f))
3399 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
3400 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3402 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
3403 if (r_ambient.value >= (1.0f/64.0f))
3404 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
3406 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3408 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
3409 if (r_ambient.value >= (1.0f/64.0f))
3410 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
3413 if (t->currentskinframe->glow != NULL)
3414 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
3415 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3417 // if this is opaque use alpha blend which will darken the earlier
3420 // if this is an alpha blended material, all the earlier passes
3421 // were darkened by fog already, so we only need to add the fog
3422 // color ontop through the fog mask texture
3424 // if this is an additive blended material, all the earlier passes
3425 // were darkened by fog already, and we should not add fog color
3426 // (because the background was not darkened, there is no fog color
3427 // that was lost behind it).
3428 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
3435 void R_UpdateAllTextureInfo(entity_render_t *ent)
3439 for (i = 0;i < ent->model->num_texturesperskin;i++)
3440 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3443 rsurfacestate_t rsurface;
3445 void R_Mesh_ResizeArrays(int newvertices)
3448 if (rsurface.array_size >= newvertices)
3450 if (rsurface.array_modelvertex3f)
3451 Mem_Free(rsurface.array_modelvertex3f);
3452 rsurface.array_size = (newvertices + 1023) & ~1023;
3453 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3454 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3455 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3456 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3457 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3458 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3459 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3460 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3461 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3462 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3463 rsurface.array_color4f = base + rsurface.array_size * 27;
3464 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3467 void RSurf_CleanUp(void)
3470 if (rsurface.mode == RSURFMODE_GLSL)
3472 qglUseProgramObjectARB(0);CHECKGLERROR
3474 GL_AlphaTest(false);
3475 rsurface.mode = RSURFMODE_NONE;
3476 rsurface.uselightmaptexture = false;
3477 rsurface.texture = NULL;
3480 void RSurf_ActiveWorldEntity(void)
3482 model_t *model = r_refdef.worldmodel;
3484 if (rsurface.array_size < model->surfmesh.num_vertices)
3485 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3486 rsurface.matrix = identitymatrix;
3487 rsurface.inversematrix = identitymatrix;
3488 R_Mesh_Matrix(&identitymatrix);
3489 VectorCopy(r_view.origin, rsurface.modelorg);
3490 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3491 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3492 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3493 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3494 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3495 rsurface.frameblend[0].frame = 0;
3496 rsurface.frameblend[0].lerp = 1;
3497 rsurface.frameblend[1].frame = 0;
3498 rsurface.frameblend[1].lerp = 0;
3499 rsurface.frameblend[2].frame = 0;
3500 rsurface.frameblend[2].lerp = 0;
3501 rsurface.frameblend[3].frame = 0;
3502 rsurface.frameblend[3].lerp = 0;
3503 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3504 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3505 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3506 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3507 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3508 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3509 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3510 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3511 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3512 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3513 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3514 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3515 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3516 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3517 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3518 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3519 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3520 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3521 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3522 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3523 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3524 rsurface.modelelement3i = model->surfmesh.data_element3i;
3525 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3526 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3527 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3528 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3529 rsurface.modelsurfaces = model->data_surfaces;
3530 rsurface.generatedvertex = false;
3531 rsurface.vertex3f = rsurface.modelvertex3f;
3532 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3533 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3534 rsurface.svector3f = rsurface.modelsvector3f;
3535 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3536 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3537 rsurface.tvector3f = rsurface.modeltvector3f;
3538 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3539 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3540 rsurface.normal3f = rsurface.modelnormal3f;
3541 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3542 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3543 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3546 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3548 model_t *model = ent->model;
3550 if (rsurface.array_size < model->surfmesh.num_vertices)
3551 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3552 rsurface.matrix = ent->matrix;
3553 rsurface.inversematrix = ent->inversematrix;
3554 R_Mesh_Matrix(&rsurface.matrix);
3555 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3556 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3557 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3558 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3559 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3560 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3561 rsurface.frameblend[0] = ent->frameblend[0];
3562 rsurface.frameblend[1] = ent->frameblend[1];
3563 rsurface.frameblend[2] = ent->frameblend[2];
3564 rsurface.frameblend[3] = ent->frameblend[3];
3565 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3569 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3570 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3571 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3572 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3573 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3575 else if (wantnormals)
3577 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3578 rsurface.modelsvector3f = NULL;
3579 rsurface.modeltvector3f = NULL;
3580 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3581 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3585 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3586 rsurface.modelsvector3f = NULL;
3587 rsurface.modeltvector3f = NULL;
3588 rsurface.modelnormal3f = NULL;
3589 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3591 rsurface.modelvertex3f_bufferobject = 0;
3592 rsurface.modelvertex3f_bufferoffset = 0;
3593 rsurface.modelsvector3f_bufferobject = 0;
3594 rsurface.modelsvector3f_bufferoffset = 0;
3595 rsurface.modeltvector3f_bufferobject = 0;
3596 rsurface.modeltvector3f_bufferoffset = 0;
3597 rsurface.modelnormal3f_bufferobject = 0;
3598 rsurface.modelnormal3f_bufferoffset = 0;
3599 rsurface.generatedvertex = true;
3603 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3604 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3605 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3606 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3607 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3608 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3609 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3610 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3611 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3612 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3613 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3614 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3615 rsurface.generatedvertex = false;
3617 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3618 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3619 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3620 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3621 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3622 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3623 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3624 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3625 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3626 rsurface.modelelement3i = model->surfmesh.data_element3i;
3627 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3628 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3629 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3630 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3631 rsurface.modelsurfaces = model->data_surfaces;
3632 rsurface.vertex3f = rsurface.modelvertex3f;
3633 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3634 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3635 rsurface.svector3f = rsurface.modelsvector3f;
3636 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3637 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3638 rsurface.tvector3f = rsurface.modeltvector3f;
3639 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3640 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3641 rsurface.normal3f = rsurface.modelnormal3f;
3642 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3643 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3644 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3647 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3648 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3651 int texturesurfaceindex;
3656 const float *v1, *in_tc;
3658 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3660 q3shaderinfo_deform_t *deform;
3661 // 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
3662 if (rsurface.generatedvertex)
3664 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3665 generatenormals = true;
3666 for (i = 0;i < Q3MAXDEFORMS;i++)
3668 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3670 generatetangents = true;
3671 generatenormals = true;
3673 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3674 generatenormals = true;
3676 if (generatenormals && !rsurface.modelnormal3f)
3678 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3679 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3680 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3681 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3683 if (generatetangents && !rsurface.modelsvector3f)
3685 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3686 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3687 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3688 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3689 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3690 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3691 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);
3694 rsurface.vertex3f = rsurface.modelvertex3f;
3695 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3696 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3697 rsurface.svector3f = rsurface.modelsvector3f;
3698 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3699 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3700 rsurface.tvector3f = rsurface.modeltvector3f;
3701 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3702 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3703 rsurface.normal3f = rsurface.modelnormal3f;
3704 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3705 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3706 // if vertices are deformed (sprite flares and things in maps, possibly
3707 // water waves, bulges and other deformations), generate them into
3708 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3709 // (may be static model data or generated data for an animated model, or
3710 // the previous deform pass)
3711 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3713 switch (deform->deform)
3716 case Q3DEFORM_PROJECTIONSHADOW:
3717 case Q3DEFORM_TEXT0:
3718 case Q3DEFORM_TEXT1:
3719 case Q3DEFORM_TEXT2:
3720 case Q3DEFORM_TEXT3:
3721 case Q3DEFORM_TEXT4:
3722 case Q3DEFORM_TEXT5:
3723 case Q3DEFORM_TEXT6:
3724 case Q3DEFORM_TEXT7:
3727 case Q3DEFORM_AUTOSPRITE:
3728 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3729 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3730 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3731 VectorNormalize(newforward);
3732 VectorNormalize(newright);
3733 VectorNormalize(newup);
3734 // make deformed versions of only the model vertices used by the specified surfaces
3735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3737 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3738 // a single autosprite surface can contain multiple sprites...
3739 for (j = 0;j < surface->num_vertices - 3;j += 4)
3741 VectorClear(center);
3742 for (i = 0;i < 4;i++)
3743 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3744 VectorScale(center, 0.25f, center);
3745 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3746 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3747 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3748 for (i = 0;i < 4;i++)
3750 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3751 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3754 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);
3755 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);
3757 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3758 rsurface.vertex3f_bufferobject = 0;
3759 rsurface.vertex3f_bufferoffset = 0;
3760 rsurface.svector3f = rsurface.array_deformedsvector3f;
3761 rsurface.svector3f_bufferobject = 0;
3762 rsurface.svector3f_bufferoffset = 0;
3763 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3764 rsurface.tvector3f_bufferobject = 0;
3765 rsurface.tvector3f_bufferoffset = 0;
3766 rsurface.normal3f = rsurface.array_deformednormal3f;
3767 rsurface.normal3f_bufferobject = 0;
3768 rsurface.normal3f_bufferoffset = 0;
3770 case Q3DEFORM_AUTOSPRITE2:
3771 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3772 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3773 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3774 VectorNormalize(newforward);
3775 VectorNormalize(newright);
3776 VectorNormalize(newup);
3777 // make deformed versions of only the model vertices used by the specified surfaces
3778 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3780 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3781 const float *v1, *v2;
3789 // a single autosprite surface can contain multiple sprites...
3790 for (j = 0;j < surface->num_vertices - 3;j += 4)
3792 VectorClear(center);
3793 for (i = 0;i < 4;i++)
3794 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3795 VectorScale(center, 0.25f, center);
3796 shortest[0].quadedge = shortest[1].quadedge = 0;
3797 shortest[0].length2 = shortest[1].length2 = 0;
3798 // find the two shortest edges, then use them to define the
3799 // axis vectors for rotating around the central axis
3800 for (i = 0;i < 6;i++)
3802 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3803 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3804 l = VectorDistance2(v1, v2);
3805 if (shortest[0].length2 > l || i == 0)
3807 shortest[1] = shortest[0];
3808 shortest[0].length2 = l;
3809 shortest[0].quadedge = i;
3811 else if (shortest[1].length2 > l || i == 1)
3813 shortest[1].length2 = l;
3814 shortest[1].quadedge = i;
3817 // this calculates the midpoints *2 (not bothering to average) of the two shortest edges, and subtracts one from the other to get the up vector
3818 for (i = 0;i < 3;i++)
3820 right[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
3821 + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i];
3822 up[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]
3823 + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
3824 - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i]
3825 - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i];
3827 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3828 VectorSubtract(rsurface.modelorg, center, forward);
3829 CrossProduct(up, forward, newright);
3830 // normalize the vectors involved
3831 VectorNormalize(right);
3832 VectorNormalize(newright);
3833 // rotate the quad around the up axis vector, this is made
3834 // especially easy by the fact we know the quad is flat,
3835 // so we only have to subtract the center position and
3836 // measure distance along the right vector, and then
3837 // multiply that by the newright vector and add back the
3839 // we also need to subtract the old position to undo the
3840 // displacement from the center, which we do with a
3841 // DotProduct, the subtraction/addition of center is also
3842 // optimized into DotProducts here
3843 l = DotProduct(newright, center) - DotProduct(right, center);
3844 for (i = 0;i < 4;i++)
3846 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3847 f = DotProduct(right, v1) - DotProduct(newright, v1) + l;
3848 VectorMA(v1, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3851 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);
3852 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);
3854 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3855 rsurface.vertex3f_bufferobject = 0;
3856 rsurface.vertex3f_bufferoffset = 0;
3857 rsurface.svector3f = rsurface.array_deformedsvector3f;
3858 rsurface.svector3f_bufferobject = 0;
3859 rsurface.svector3f_bufferoffset = 0;
3860 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3861 rsurface.tvector3f_bufferobject = 0;
3862 rsurface.tvector3f_bufferoffset = 0;
3863 rsurface.normal3f = rsurface.array_deformednormal3f;
3864 rsurface.normal3f_bufferobject = 0;
3865 rsurface.normal3f_bufferoffset = 0;
3867 case Q3DEFORM_NORMAL:
3868 // deform the normals to make reflections wavey
3869 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3871 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3872 for (j = 0;j < surface->num_vertices;j++)
3875 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
3876 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
3877 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
3878 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3879 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3880 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3881 VectorNormalize(normal);
3883 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);
3885 rsurface.svector3f = rsurface.array_deformedsvector3f;
3886 rsurface.svector3f_bufferobject = 0;
3887 rsurface.svector3f_bufferoffset = 0;
3888 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3889 rsurface.tvector3f_bufferobject = 0;
3890 rsurface.tvector3f_bufferoffset = 0;
3891 rsurface.normal3f = rsurface.array_deformednormal3f;
3892 rsurface.normal3f_bufferobject = 0;
3893 rsurface.normal3f_bufferoffset = 0;
3896 // deform vertex array to make wavey water and flags and such
3897 waveparms[0] = deform->waveparms[0];
3898 waveparms[1] = deform->waveparms[1];
3899 waveparms[2] = deform->waveparms[2];
3900 waveparms[3] = deform->waveparms[3];
3901 // this is how a divisor of vertex influence on deformation
3902 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
3903 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
3904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3906 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3907 for (j = 0;j < surface->num_vertices;j++)
3909 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
3910 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
3911 // if the wavefunc depends on time, evaluate it per-vertex
3914 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
3915 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
3917 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
3920 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3921 rsurface.vertex3f_bufferobject = 0;
3922 rsurface.vertex3f_bufferoffset = 0;
3924 case Q3DEFORM_BULGE:
3925 // deform vertex array to make the surface have moving bulges
3926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3928 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3929 for (j = 0;j < surface->num_vertices;j++)
3931 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
3932 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
3935 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3936 rsurface.vertex3f_bufferobject = 0;
3937 rsurface.vertex3f_bufferoffset = 0;
3940 // deform vertex array
3941 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
3942 VectorScale(deform->parms, scale, waveparms);
3943 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3945 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3946 for (j = 0;j < surface->num_vertices;j++)
3947 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
3949 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3950 rsurface.vertex3f_bufferobject = 0;
3951 rsurface.vertex3f_bufferoffset = 0;
3955 // generate texcoords based on the chosen texcoord source
3956 switch(rsurface.texture->tcgen.tcgen)
3959 case Q3TCGEN_TEXTURE:
3960 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3961 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
3962 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
3964 case Q3TCGEN_LIGHTMAP:
3965 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
3966 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
3967 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
3969 case Q3TCGEN_VECTOR:
3970 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3972 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3973 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)
3975 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
3976 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
3979 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
3980 rsurface.texcoordtexture2f_bufferobject = 0;
3981 rsurface.texcoordtexture2f_bufferoffset = 0;
3983 case Q3TCGEN_ENVIRONMENT:
3984 // make environment reflections using a spheremap
3985 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3987 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3988 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
3989 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
3990 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
3991 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
3993 float l, d, eyedir[3];
3994 VectorSubtract(rsurface.modelorg, vertex, eyedir);
3995 l = 0.5f / VectorLength(eyedir);
3996 d = DotProduct(normal, eyedir)*2;
3997 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
3998 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4001 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4002 rsurface.texcoordtexture2f_bufferobject = 0;
4003 rsurface.texcoordtexture2f_bufferoffset = 0;
4006 // the only tcmod that needs software vertex processing is turbulent, so
4007 // check for it here and apply the changes if needed
4008 // and we only support that as the first one
4009 // (handling a mixture of turbulent and other tcmods would be problematic
4010 // without punting it entirely to a software path)
4011 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4013 amplitude = rsurface.texture->tcmods[0].parms[1];
4014 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4015 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4017 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4018 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)
4020 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4021 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4024 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4025 rsurface.texcoordtexture2f_bufferobject = 0;
4026 rsurface.texcoordtexture2f_bufferoffset = 0;
4028 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4029 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4030 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4031 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4034 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4037 const msurface_t *surface = texturesurfacelist[0];
4038 const msurface_t *surface2;
4043 // TODO: lock all array ranges before render, rather than on each surface
4044 if (texturenumsurfaces == 1)
4046 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4047 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4049 else if (r_batchmode.integer == 2)
4051 #define MAXBATCHTRIANGLES 4096
4052 int batchtriangles = 0;
4053 int batchelements[MAXBATCHTRIANGLES*3];
4054 for (i = 0;i < texturenumsurfaces;i = j)
4056 surface = texturesurfacelist[i];
4058 if (surface->num_triangles > MAXBATCHTRIANGLES)
4060 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4063 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4064 batchtriangles = surface->num_triangles;
4065 firstvertex = surface->num_firstvertex;
4066 endvertex = surface->num_firstvertex + surface->num_vertices;
4067 for (;j < texturenumsurfaces;j++)
4069 surface2 = texturesurfacelist[j];
4070 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4072 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4073 batchtriangles += surface2->num_triangles;
4074 firstvertex = min(firstvertex, surface2->num_firstvertex);
4075 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4077 surface2 = texturesurfacelist[j-1];
4078 numvertices = endvertex - firstvertex;
4079 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4082 else if (r_batchmode.integer == 1)
4084 for (i = 0;i < texturenumsurfaces;i = j)
4086 surface = texturesurfacelist[i];
4087 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4088 if (texturesurfacelist[j] != surface2)
4090 surface2 = texturesurfacelist[j-1];
4091 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4092 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4093 GL_LockArrays(surface->num_firstvertex, numvertices);
4094 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4099 for (i = 0;i < texturenumsurfaces;i++)
4101 surface = texturesurfacelist[i];
4102 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4103 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4108 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4112 const msurface_t *surface = texturesurfacelist[0];
4113 const msurface_t *surface2;
4118 // TODO: lock all array ranges before render, rather than on each surface
4119 if (texturenumsurfaces == 1)
4121 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4122 if (deluxemaptexunit >= 0)
4123 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4124 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4125 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4127 else if (r_batchmode.integer == 2)
4129 #define MAXBATCHTRIANGLES 4096
4130 int batchtriangles = 0;
4131 int batchelements[MAXBATCHTRIANGLES*3];
4132 for (i = 0;i < texturenumsurfaces;i = j)
4134 surface = texturesurfacelist[i];
4135 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4136 if (deluxemaptexunit >= 0)
4137 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4139 if (surface->num_triangles > MAXBATCHTRIANGLES)
4141 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4144 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4145 batchtriangles = surface->num_triangles;
4146 firstvertex = surface->num_firstvertex;
4147 endvertex = surface->num_firstvertex + surface->num_vertices;
4148 for (;j < texturenumsurfaces;j++)
4150 surface2 = texturesurfacelist[j];
4151 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4153 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4154 batchtriangles += surface2->num_triangles;
4155 firstvertex = min(firstvertex, surface2->num_firstvertex);
4156 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4158 surface2 = texturesurfacelist[j-1];
4159 numvertices = endvertex - firstvertex;
4160 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4163 else if (r_batchmode.integer == 1)
4166 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4167 for (i = 0;i < texturenumsurfaces;i = j)
4169 surface = texturesurfacelist[i];
4170 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4171 if (texturesurfacelist[j] != surface2)
4173 Con_Printf(" %i", j - i);
4176 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4178 for (i = 0;i < texturenumsurfaces;i = j)
4180 surface = texturesurfacelist[i];
4181 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4182 if (deluxemaptexunit >= 0)
4183 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4184 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4185 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4188 Con_Printf(" %i", j - i);
4190 surface2 = texturesurfacelist[j-1];
4191 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4192 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4193 GL_LockArrays(surface->num_firstvertex, numvertices);
4194 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4202 for (i = 0;i < texturenumsurfaces;i++)
4204 surface = texturesurfacelist[i];
4205 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4206 if (deluxemaptexunit >= 0)
4207 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4208 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4209 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4214 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4217 int texturesurfaceindex;
4218 if (r_showsurfaces.integer == 2)
4220 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4222 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4223 for (j = 0;j < surface->num_triangles;j++)
4225 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4226 GL_Color(f, f, f, 1);
4227 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
4233 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4235 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4236 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4237 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
4238 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4239 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4244 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4246 int texturesurfaceindex;
4250 if (rsurface.lightmapcolor4f)
4252 // generate color arrays for the surfaces in this list
4253 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4255 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4256 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)
4258 f = FogPoint_Model(v);
4268 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4270 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4271 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)
4273 f = FogPoint_Model(v);
4281 rsurface.lightmapcolor4f = rsurface.array_color4f;
4282 rsurface.lightmapcolor4f_bufferobject = 0;
4283 rsurface.lightmapcolor4f_bufferoffset = 0;
4286 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4288 int texturesurfaceindex;
4291 if (!rsurface.lightmapcolor4f)
4293 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4295 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4296 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)
4304 rsurface.lightmapcolor4f = rsurface.array_color4f;
4305 rsurface.lightmapcolor4f_bufferobject = 0;
4306 rsurface.lightmapcolor4f_bufferoffset = 0;
4309 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4312 rsurface.lightmapcolor4f = NULL;
4313 rsurface.lightmapcolor4f_bufferobject = 0;
4314 rsurface.lightmapcolor4f_bufferoffset = 0;
4315 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4316 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4317 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4318 GL_Color(r, g, b, a);
4319 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4322 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4324 // TODO: optimize applyfog && applycolor case
4325 // just apply fog if necessary, and tint the fog color array if necessary
4326 rsurface.lightmapcolor4f = NULL;
4327 rsurface.lightmapcolor4f_bufferobject = 0;
4328 rsurface.lightmapcolor4f_bufferoffset = 0;
4329 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4330 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4331 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4332 GL_Color(r, g, b, a);
4333 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4336 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4338 int texturesurfaceindex;
4342 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4344 // generate color arrays for the surfaces in this list
4345 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4347 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4348 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4350 if (surface->lightmapinfo->samples)
4352 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4353 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4354 VectorScale(lm, scale, c);
4355 if (surface->lightmapinfo->styles[1] != 255)
4357 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4359 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4360 VectorMA(c, scale, lm, c);
4361 if (surface->lightmapinfo->styles[2] != 255)
4364 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4365 VectorMA(c, scale, lm, c);
4366 if (surface->lightmapinfo->styles[3] != 255)
4369 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4370 VectorMA(c, scale, lm, c);
4380 rsurface.lightmapcolor4f = rsurface.array_color4f;
4381 rsurface.lightmapcolor4f_bufferobject = 0;
4382 rsurface.lightmapcolor4f_bufferoffset = 0;
4386 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4387 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4388 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4390 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4391 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4392 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4393 GL_Color(r, g, b, a);
4394 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4397 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4399 int texturesurfaceindex;
4403 vec3_t ambientcolor;
4404 vec3_t diffusecolor;
4408 VectorCopy(rsurface.modellight_lightdir, lightdir);
4409 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4410 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4411 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4412 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4413 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4414 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4415 if (VectorLength2(diffusecolor) > 0)
4417 // generate color arrays for the surfaces in this list
4418 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4420 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4421 int numverts = surface->num_vertices;
4422 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4423 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4424 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4425 // q3-style directional shading
4426 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4428 if ((f = DotProduct(c2, lightdir)) > 0)
4429 VectorMA(ambientcolor, f, diffusecolor, c);
4431 VectorCopy(ambientcolor, c);
4440 rsurface.lightmapcolor4f = rsurface.array_color4f;
4441 rsurface.lightmapcolor4f_bufferobject = 0;
4442 rsurface.lightmapcolor4f_bufferoffset = 0;
4446 r = ambientcolor[0];
4447 g = ambientcolor[1];
4448 b = ambientcolor[2];
4449 rsurface.lightmapcolor4f = NULL;
4450 rsurface.lightmapcolor4f_bufferobject = 0;
4451 rsurface.lightmapcolor4f_bufferoffset = 0;
4453 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4454 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4455 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4456 GL_Color(r, g, b, a);
4457 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4460 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4462 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4463 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4464 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4465 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4466 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4468 rsurface.mode = RSURFMODE_SHOWSURFACES;
4470 GL_BlendFunc(GL_ONE, GL_ZERO);
4471 R_Mesh_ColorPointer(NULL, 0, 0);
4472 R_Mesh_ResetTextureState();
4474 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4475 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4478 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4480 // transparent sky would be ridiculous
4481 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4483 if (rsurface.mode != RSURFMODE_SKY)
4485 if (rsurface.mode == RSURFMODE_GLSL)
4487 qglUseProgramObjectARB(0);CHECKGLERROR
4489 rsurface.mode = RSURFMODE_SKY;
4493 skyrendernow = false;
4495 // restore entity matrix
4496 R_Mesh_Matrix(&rsurface.matrix);
4498 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4499 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4500 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4501 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4503 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4504 // skymasking on them, and Quake3 never did sky masking (unlike
4505 // software Quake and software Quake2), so disable the sky masking
4506 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4507 // and skymasking also looks very bad when noclipping outside the
4508 // level, so don't use it then either.
4509 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4511 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4512 R_Mesh_ColorPointer(NULL, 0, 0);
4513 R_Mesh_ResetTextureState();
4514 if (skyrendermasked)
4516 // depth-only (masking)
4517 GL_ColorMask(0,0,0,0);
4518 // just to make sure that braindead drivers don't draw
4519 // anything despite that colormask...
4520 GL_BlendFunc(GL_ZERO, GL_ONE);
4525 GL_BlendFunc(GL_ONE, GL_ZERO);
4527 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4528 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4529 if (skyrendermasked)
4530 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4534 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4536 if (rsurface.mode != RSURFMODE_GLSL)
4538 rsurface.mode = RSURFMODE_GLSL;
4539 R_Mesh_ResetTextureState();
4542 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4543 if (!r_glsl_permutation)
4546 if (rsurface.lightmode == 2)
4547 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4549 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4550 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4551 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4552 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4553 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4554 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4556 GL_Color(rsurface.texture->currentlayers[0].color[0], rsurface.texture->currentlayers[0].color[1], rsurface.texture->currentlayers[0].color[2], rsurface.texture->currentlayers[0].color[3]);
4557 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4559 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4560 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4561 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4562 R_Mesh_ColorPointer(NULL, 0, 0);
4564 else if (rsurface.uselightmaptexture)
4566 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4567 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4568 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4569 R_Mesh_ColorPointer(NULL, 0, 0);
4573 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4574 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4575 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4576 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4579 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4580 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4582 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4583 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4588 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4590 // OpenGL 1.3 path - anything not completely ancient
4591 int texturesurfaceindex;
4592 qboolean applycolor;
4596 const texturelayer_t *layer;
4597 if (rsurface.mode != RSURFMODE_MULTIPASS)
4598 rsurface.mode = RSURFMODE_MULTIPASS;
4599 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4600 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4603 int layertexrgbscale;
4604 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4606 if (layerindex == 0)
4610 GL_AlphaTest(false);
4611 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4614 GL_DepthMask(layer->depthmask);
4615 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4616 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4618 layertexrgbscale = 4;
4619 VectorScale(layer->color, 0.25f, layercolor);
4621 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4623 layertexrgbscale = 2;
4624 VectorScale(layer->color, 0.5f, layercolor);
4628 layertexrgbscale = 1;
4629 VectorScale(layer->color, 1.0f, layercolor);
4631 layercolor[3] = layer->color[3];
4632 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4633 R_Mesh_ColorPointer(NULL, 0, 0);
4634 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4635 switch (layer->type)
4637 case TEXTURELAYERTYPE_LITTEXTURE:
4638 memset(&m, 0, sizeof(m));
4639 m.tex[0] = R_GetTexture(r_texture_white);
4640 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4641 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4642 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4643 m.tex[1] = R_GetTexture(layer->texture);
4644 m.texmatrix[1] = layer->texmatrix;
4645 m.texrgbscale[1] = layertexrgbscale;
4646 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4647 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4648 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4649 R_Mesh_TextureState(&m);
4650 if (rsurface.lightmode == 2)
4651 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4652 else if (rsurface.uselightmaptexture)
4653 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4655 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4657 case TEXTURELAYERTYPE_TEXTURE:
4658 memset(&m, 0, sizeof(m));
4659 m.tex[0] = R_GetTexture(layer->texture);
4660 m.texmatrix[0] = layer->texmatrix;
4661 m.texrgbscale[0] = layertexrgbscale;
4662 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4663 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4664 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4665 R_Mesh_TextureState(&m);
4666 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4668 case TEXTURELAYERTYPE_FOG:
4669 memset(&m, 0, sizeof(m));
4670 m.texrgbscale[0] = layertexrgbscale;
4673 m.tex[0] = R_GetTexture(layer->texture);
4674 m.texmatrix[0] = layer->texmatrix;
4675 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4676 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4677 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4679 R_Mesh_TextureState(&m);
4680 // generate a color array for the fog pass
4681 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4682 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4686 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4687 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)
4689 f = 1 - FogPoint_Model(v);
4690 c[0] = layercolor[0];
4691 c[1] = layercolor[1];
4692 c[2] = layercolor[2];
4693 c[3] = f * layercolor[3];
4696 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4699 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4701 GL_LockArrays(0, 0);
4704 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4706 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4707 GL_AlphaTest(false);
4711 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4713 // OpenGL 1.1 - crusty old voodoo path
4714 int texturesurfaceindex;
4718 const texturelayer_t *layer;
4719 if (rsurface.mode != RSURFMODE_MULTIPASS)
4720 rsurface.mode = RSURFMODE_MULTIPASS;
4721 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4722 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4726 if (layerindex == 0)
4730 GL_AlphaTest(false);
4731 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4734 GL_DepthMask(layer->depthmask);
4735 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4736 R_Mesh_ColorPointer(NULL, 0, 0);
4737 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4738 switch (layer->type)
4740 case TEXTURELAYERTYPE_LITTEXTURE:
4741 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4743 // two-pass lit texture with 2x rgbscale
4744 // first the lightmap pass
4745 memset(&m, 0, sizeof(m));
4746 m.tex[0] = R_GetTexture(r_texture_white);
4747 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4748 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4749 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4750 R_Mesh_TextureState(&m);
4751 if (rsurface.lightmode == 2)
4752 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4753 else if (rsurface.uselightmaptexture)
4754 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4756 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4757 GL_LockArrays(0, 0);
4758 // then apply the texture to it
4759 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4760 memset(&m, 0, sizeof(m));
4761 m.tex[0] = R_GetTexture(layer->texture);
4762 m.texmatrix[0] = layer->texmatrix;
4763 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4764 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4765 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4766 R_Mesh_TextureState(&m);
4767 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);
4771 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4772 memset(&m, 0, sizeof(m));
4773 m.tex[0] = R_GetTexture(layer->texture);
4774 m.texmatrix[0] = layer->texmatrix;
4775 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4776 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4777 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4778 R_Mesh_TextureState(&m);
4779 if (rsurface.lightmode == 2)
4780 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);
4782 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);
4785 case TEXTURELAYERTYPE_TEXTURE:
4786 // singletexture unlit texture with transparency support
4787 memset(&m, 0, sizeof(m));
4788 m.tex[0] = R_GetTexture(layer->texture);
4789 m.texmatrix[0] = layer->texmatrix;
4790 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4791 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4792 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4793 R_Mesh_TextureState(&m);
4794 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);
4796 case TEXTURELAYERTYPE_FOG:
4797 // singletexture fogging
4798 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4801 memset(&m, 0, sizeof(m));
4802 m.tex[0] = R_GetTexture(layer->texture);
4803 m.texmatrix[0] = layer->texmatrix;
4804 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4805 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4806 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4807 R_Mesh_TextureState(&m);
4810 R_Mesh_ResetTextureState();
4811 // generate a color array for the fog pass
4812 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4816 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4817 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)
4819 f = 1 - FogPoint_Model(v);
4820 c[0] = layer->color[0];
4821 c[1] = layer->color[1];
4822 c[2] = layer->color[2];
4823 c[3] = f * layer->color[3];
4826 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4829 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4831 GL_LockArrays(0, 0);
4834 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4836 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4837 GL_AlphaTest(false);
4841 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4843 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4845 rsurface.rtlight = NULL;
4849 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4851 if (rsurface.mode != RSURFMODE_MULTIPASS)
4852 rsurface.mode = RSURFMODE_MULTIPASS;
4853 if (r_depthfirst.integer == 3)
4855 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4856 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4860 GL_ColorMask(0,0,0,0);
4863 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4864 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4865 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4867 GL_BlendFunc(GL_ONE, GL_ZERO);
4869 GL_AlphaTest(false);
4870 R_Mesh_ColorPointer(NULL, 0, 0);
4871 R_Mesh_ResetTextureState();
4872 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4873 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4874 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4875 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4877 else if (r_depthfirst.integer == 3)
4879 else if (r_showsurfaces.integer)
4881 if (rsurface.mode != RSURFMODE_MULTIPASS)
4882 rsurface.mode = RSURFMODE_MULTIPASS;
4883 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4884 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4886 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4887 GL_BlendFunc(GL_ONE, GL_ZERO);
4888 GL_DepthMask(writedepth);
4890 GL_AlphaTest(false);
4891 R_Mesh_ColorPointer(NULL, 0, 0);
4892 R_Mesh_ResetTextureState();
4893 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4894 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4895 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4897 else if (gl_lightmaps.integer)
4900 if (rsurface.mode != RSURFMODE_MULTIPASS)
4901 rsurface.mode = RSURFMODE_MULTIPASS;
4902 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4904 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4905 GL_BlendFunc(GL_ONE, GL_ZERO);
4906 GL_DepthMask(writedepth);
4908 GL_AlphaTest(false);
4909 R_Mesh_ColorPointer(NULL, 0, 0);
4910 memset(&m, 0, sizeof(m));
4911 m.tex[0] = R_GetTexture(r_texture_white);
4912 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4913 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4914 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4915 R_Mesh_TextureState(&m);
4916 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
4917 if (rsurface.lightmode == 2)
4918 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4919 else if (rsurface.uselightmaptexture)
4920 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4922 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4923 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4925 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
4927 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4928 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4930 else if (rsurface.texture->currentnumlayers)
4932 // write depth for anything we skipped on the depth-only pass earlier
4933 if (!writedepth && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4935 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4936 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4937 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4938 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4939 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4940 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4941 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4942 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
4943 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
4944 if (r_glsl.integer && gl_support_fragment_shader)
4945 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4946 else if (gl_combine.integer && r_textureunits.integer >= 2)
4947 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4949 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4950 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4953 GL_LockArrays(0, 0);
4956 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4959 int texturenumsurfaces, endsurface;
4961 msurface_t *surface;
4962 msurface_t *texturesurfacelist[1024];
4964 // if the model is static it doesn't matter what value we give for
4965 // wantnormals and wanttangents, so this logic uses only rules applicable
4966 // to a model, knowing that they are meaningless otherwise
4967 if (ent == r_refdef.worldentity)
4968 RSurf_ActiveWorldEntity();
4969 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4970 RSurf_ActiveModelEntity(ent, false, false);
4972 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4974 for (i = 0;i < numsurfaces;i = j)
4977 surface = rsurface.modelsurfaces + surfacelist[i];
4978 texture = surface->texture;
4979 R_UpdateTextureInfo(ent, texture);
4980 rsurface.texture = texture->currentframe;
4981 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
4982 // scan ahead until we find a different texture
4983 endsurface = min(i + 1024, numsurfaces);
4984 texturenumsurfaces = 0;
4985 texturesurfacelist[texturenumsurfaces++] = surface;
4986 for (;j < endsurface;j++)
4988 surface = rsurface.modelsurfaces + surfacelist[j];
4989 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
4991 texturesurfacelist[texturenumsurfaces++] = surface;
4993 // render the range of surfaces
4994 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5000 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5003 vec3_t tempcenter, center;
5005 // break the surface list down into batches by texture and use of lightmapping
5006 for (i = 0;i < numsurfaces;i = j)
5009 // texture is the base texture pointer, rsurface.texture is the
5010 // current frame/skin the texture is directing us to use (for example
5011 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5012 // use skin 1 instead)
5013 texture = surfacelist[i]->texture;
5014 rsurface.texture = texture->currentframe;
5015 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5016 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5018 // if this texture is not the kind we want, skip ahead to the next one
5019 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5023 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5025 // transparent surfaces get pushed off into the transparent queue
5026 const msurface_t *surface = surfacelist[i];
5029 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5030 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5031 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5032 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5033 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5037 // simply scan ahead until we find a different texture or lightmap state
5038 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5040 // render the range of surfaces
5041 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5046 float locboxvertex3f[6*4*3] =
5048 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5049 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5050 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5051 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5052 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5053 1,0,0, 0,0,0, 0,1,0, 1,1,0
5056 int locboxelement3i[6*2*3] =
5066 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5069 cl_locnode_t *loc = (cl_locnode_t *)ent;
5071 float vertex3f[6*4*3];
5073 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5074 GL_DepthMask(false);
5075 GL_DepthRange(0, 1);
5076 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5078 GL_CullFace(GL_NONE);
5079 R_Mesh_Matrix(&identitymatrix);
5081 R_Mesh_VertexPointer(vertex3f, 0, 0);
5082 R_Mesh_ColorPointer(NULL, 0, 0);
5083 R_Mesh_ResetTextureState();
5086 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5087 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5088 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5089 surfacelist[0] < 0 ? 0.5f : 0.125f);
5091 if (VectorCompare(loc->mins, loc->maxs))
5093 VectorSet(size, 2, 2, 2);
5094 VectorMA(loc->mins, -0.5f, size, mins);
5098 VectorCopy(loc->mins, mins);
5099 VectorSubtract(loc->maxs, loc->mins, size);
5102 for (i = 0;i < 6*4*3;)
5103 for (j = 0;j < 3;j++, i++)
5104 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5106 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5109 void R_DrawLocs(void)
5112 cl_locnode_t *loc, *nearestloc;
5114 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5115 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5117 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5118 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5122 void R_DrawCollisionBrushes(entity_render_t *ent)
5126 msurface_t *surface;
5127 model_t *model = ent->model;
5128 if (!model->brush.num_brushes)
5131 R_Mesh_ColorPointer(NULL, 0, 0);
5132 R_Mesh_ResetTextureState();
5133 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5134 GL_DepthMask(false);
5135 GL_DepthRange(0, 1);
5136 GL_DepthTest(!r_showdisabledepthtest.integer);
5137 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5138 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5139 if (brush->colbrushf && brush->colbrushf->numtriangles)
5140 R_DrawCollisionBrush(brush->colbrushf);
5141 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5142 if (surface->num_collisiontriangles)
5143 R_DrawCollisionSurface(ent, surface);
5144 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5147 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5150 const int *elements;
5151 msurface_t *surface;
5152 model_t *model = ent->model;
5155 GL_DepthRange(0, 1);
5156 GL_DepthTest(!r_showdisabledepthtest.integer);
5157 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5159 GL_BlendFunc(GL_ONE, GL_ZERO);
5160 R_Mesh_ColorPointer(NULL, 0, 0);
5161 R_Mesh_ResetTextureState();
5162 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5164 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5166 rsurface.texture = surface->texture->currentframe;
5167 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5169 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5172 if (!rsurface.texture->currentlayers->depthmask)
5173 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5174 else if (ent == r_refdef.worldentity)
5175 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5177 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5178 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5181 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5183 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5184 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5185 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5186 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5193 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5195 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5197 VectorCopy(rsurface.vertex3f + l * 3, v);
5198 qglVertex3f(v[0], v[1], v[2]);
5199 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5200 qglVertex3f(v[0], v[1], v[2]);
5204 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5206 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5208 VectorCopy(rsurface.vertex3f + l * 3, v);
5209 qglVertex3f(v[0], v[1], v[2]);
5210 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5211 qglVertex3f(v[0], v[1], v[2]);
5215 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5217 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5219 VectorCopy(rsurface.vertex3f + l * 3, v);
5220 qglVertex3f(v[0], v[1], v[2]);
5221 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5222 qglVertex3f(v[0], v[1], v[2]);
5229 rsurface.texture = NULL;
5232 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5233 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5235 int i, j, endj, f, flagsmask;
5236 int counttriangles = 0;
5237 msurface_t *surface, **surfacechain;
5239 model_t *model = r_refdef.worldmodel;
5240 const int maxsurfacelist = 1024;
5241 int numsurfacelist = 0;
5242 msurface_t *surfacelist[1024];
5246 RSurf_ActiveWorldEntity();
5248 // update light styles
5249 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5251 for (i = 0;i < model->brushq1.light_styles;i++)
5253 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5255 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5256 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5257 for (;(surface = *surfacechain);surfacechain++)
5258 surface->cached_dlight = true;
5263 R_UpdateAllTextureInfo(r_refdef.worldentity);
5264 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5267 rsurface.uselightmaptexture = false;
5268 rsurface.texture = NULL;
5270 j = model->firstmodelsurface;
5271 endj = j + model->nummodelsurfaces;
5274 // quickly skip over non-visible surfaces
5275 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5277 // quickly iterate over visible surfaces
5278 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5280 // process this surface
5281 surface = model->data_surfaces + j;
5282 // if this surface fits the criteria, add it to the list
5283 if (surface->num_triangles)
5285 // if lightmap parameters changed, rebuild lightmap texture
5286 if (surface->cached_dlight)
5287 R_BuildLightMap(r_refdef.worldentity, surface);
5288 // add face to draw list
5289 surfacelist[numsurfacelist++] = surface;
5290 counttriangles += surface->num_triangles;
5291 if (numsurfacelist >= maxsurfacelist)
5293 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5300 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5301 r_refdef.stats.entities_triangles += counttriangles;
5304 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5305 R_DrawCollisionBrushes(r_refdef.worldentity);
5307 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5308 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5311 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5313 int i, f, flagsmask;
5314 int counttriangles = 0;
5315 msurface_t *surface, *endsurface, **surfacechain;
5317 model_t *model = ent->model;
5318 const int maxsurfacelist = 1024;
5319 int numsurfacelist = 0;
5320 msurface_t *surfacelist[1024];
5324 // if the model is static it doesn't matter what value we give for
5325 // wantnormals and wanttangents, so this logic uses only rules applicable
5326 // to a model, knowing that they are meaningless otherwise
5327 if (ent == r_refdef.worldentity)
5328 RSurf_ActiveWorldEntity();
5329 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5330 RSurf_ActiveModelEntity(ent, false, false);
5332 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5334 // update light styles
5335 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5337 for (i = 0;i < model->brushq1.light_styles;i++)
5339 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5341 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5342 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5343 for (;(surface = *surfacechain);surfacechain++)
5344 surface->cached_dlight = true;
5349 R_UpdateAllTextureInfo(ent);
5350 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5353 rsurface.uselightmaptexture = false;
5354 rsurface.texture = NULL;
5356 surface = model->data_surfaces + model->firstmodelsurface;
5357 endsurface = surface + model->nummodelsurfaces;
5358 for (;surface < endsurface;surface++)
5360 // if this surface fits the criteria, add it to the list
5361 if (surface->num_triangles)
5363 // if lightmap parameters changed, rebuild lightmap texture
5364 if (surface->cached_dlight)
5365 R_BuildLightMap(ent, surface);
5366 // add face to draw list
5367 surfacelist[numsurfacelist++] = surface;
5368 counttriangles += surface->num_triangles;
5369 if (numsurfacelist >= maxsurfacelist)
5371 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5377 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5378 r_refdef.stats.entities_triangles += counttriangles;
5381 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5382 R_DrawCollisionBrushes(ent);
5384 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5385 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);