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)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
85 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
86 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
88 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
89 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
90 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
91 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
92 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
93 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
94 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
96 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
97 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
98 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
99 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)"};
101 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"};
103 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"};
105 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
107 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
108 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
110 extern qboolean v_flipped_state;
112 typedef struct r_glsl_bloomshader_s
115 int loc_Texture_Bloom;
117 r_glsl_bloomshader_t;
119 static struct r_bloomstate_s
124 int bloomwidth, bloomheight;
126 int screentexturewidth, screentextureheight;
127 rtexture_t *texture_screen;
129 int bloomtexturewidth, bloomtextureheight;
130 rtexture_t *texture_bloom;
132 r_glsl_bloomshader_t *shader;
134 // arrays for rendering the screen passes
135 float screentexcoord2f[8];
136 float bloomtexcoord2f[8];
137 float offsettexcoord2f[8];
141 // shadow volume bsp struct with automatically growing nodes buffer
144 rtexture_t *r_texture_blanknormalmap;
145 rtexture_t *r_texture_white;
146 rtexture_t *r_texture_black;
147 rtexture_t *r_texture_notexture;
148 rtexture_t *r_texture_whitecube;
149 rtexture_t *r_texture_normalizationcube;
150 rtexture_t *r_texture_fogattenuation;
151 //rtexture_t *r_texture_fogintensity;
153 // information about each possible shader permutation
154 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
155 // currently selected permutation
156 r_glsl_permutation_t *r_glsl_permutation;
158 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
159 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
161 // vertex coordinates for a quad that covers the screen exactly
162 const static float r_screenvertex3f[12] =
170 extern void R_DrawModelShadows(void);
172 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
175 for (i = 0;i < verts;i++)
186 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
189 for (i = 0;i < verts;i++)
199 // FIXME: move this to client?
202 if (gamemode == GAME_NEHAHRA)
204 Cvar_Set("gl_fogenable", "0");
205 Cvar_Set("gl_fogdensity", "0.2");
206 Cvar_Set("gl_fogred", "0.3");
207 Cvar_Set("gl_foggreen", "0.3");
208 Cvar_Set("gl_fogblue", "0.3");
210 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
213 float FogPoint_World(const vec3_t p)
215 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
216 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
219 float FogPoint_Model(const vec3_t p)
221 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
222 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
225 static void R_BuildBlankTextures(void)
227 unsigned char data[4];
228 data[0] = 128; // normal X
229 data[1] = 128; // normal Y
230 data[2] = 255; // normal Z
231 data[3] = 128; // height
232 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
237 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
242 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 static void R_BuildNoTexture(void)
248 unsigned char pix[16][16][4];
249 // this makes a light grey/dark grey checkerboard texture
250 for (y = 0;y < 16;y++)
252 for (x = 0;x < 16;x++)
254 if ((y < 8) ^ (x < 8))
270 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
273 static void R_BuildWhiteCube(void)
275 unsigned char data[6*1*1*4];
276 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
277 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
278 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
279 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
280 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
281 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
282 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
285 static void R_BuildNormalizationCube(void)
289 vec_t s, t, intensity;
291 unsigned char data[6][NORMSIZE][NORMSIZE][4];
292 for (side = 0;side < 6;side++)
294 for (y = 0;y < NORMSIZE;y++)
296 for (x = 0;x < NORMSIZE;x++)
298 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
299 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
334 intensity = 127.0f / sqrt(DotProduct(v, v));
335 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
336 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
337 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
338 data[side][y][x][3] = 255;
342 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
345 static void R_BuildFogTexture(void)
349 unsigned char data1[FOGWIDTH][4];
350 //unsigned char data2[FOGWIDTH][4];
351 for (x = 0;x < FOGWIDTH;x++)
353 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
358 //data2[x][0] = 255 - b;
359 //data2[x][1] = 255 - b;
360 //data2[x][2] = 255 - b;
363 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
364 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
367 static const char *builtinshaderstring =
368 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
369 "// written by Forest 'LordHavoc' Hale\n"
371 "// common definitions between vertex shader and fragment shader:\n"
373 "#ifdef __GLSL_CG_DATA_TYPES\n"
374 "#define myhalf half\n"
375 "#define myhvec2 hvec2\n"
376 "#define myhvec3 hvec3\n"
377 "#define myhvec4 hvec4\n"
379 "#define myhalf float\n"
380 "#define myhvec2 vec2\n"
381 "#define myhvec3 vec3\n"
382 "#define myhvec4 vec4\n"
385 "varying vec2 TexCoord;\n"
386 "varying vec2 TexCoordLightmap;\n"
388 "varying vec3 CubeVector;\n"
389 "varying vec3 LightVector;\n"
390 "varying vec3 EyeVector;\n"
392 "varying vec3 EyeVectorModelSpace;\n"
395 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
396 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
397 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
402 "// vertex shader specific:\n"
403 "#ifdef VERTEX_SHADER\n"
405 "uniform vec3 LightPosition;\n"
406 "uniform vec3 EyePosition;\n"
407 "uniform vec3 LightDir;\n"
409 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
413 " gl_FrontColor = gl_Color;\n"
414 " // copy the surface texcoord\n"
415 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
416 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
417 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
420 "#ifdef MODE_LIGHTSOURCE\n"
421 " // transform vertex position into light attenuation/cubemap space\n"
422 " // (-1 to +1 across the light box)\n"
423 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
425 " // transform unnormalized light direction into tangent space\n"
426 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
427 " // normalize it per pixel)\n"
428 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
429 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
430 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
431 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
434 "#ifdef MODE_LIGHTDIRECTION\n"
435 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
436 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
437 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
440 " // transform unnormalized eye direction into tangent space\n"
442 " vec3 EyeVectorModelSpace;\n"
444 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
445 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
446 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
447 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
449 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
450 " VectorS = gl_MultiTexCoord1.xyz;\n"
451 " VectorT = gl_MultiTexCoord2.xyz;\n"
452 " VectorR = gl_MultiTexCoord3.xyz;\n"
455 " // transform vertex to camera space, using ftransform to match non-VS\n"
457 " gl_Position = ftransform();\n"
460 "#endif // VERTEX_SHADER\n"
465 "// fragment shader specific:\n"
466 "#ifdef FRAGMENT_SHADER\n"
468 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
469 "uniform sampler2D Texture_Normal;\n"
470 "uniform sampler2D Texture_Color;\n"
471 "uniform sampler2D Texture_Gloss;\n"
472 "uniform samplerCube Texture_Cube;\n"
473 "uniform sampler2D Texture_Attenuation;\n"
474 "uniform sampler2D Texture_FogMask;\n"
475 "uniform sampler2D Texture_Pants;\n"
476 "uniform sampler2D Texture_Shirt;\n"
477 "uniform sampler2D Texture_Lightmap;\n"
478 "uniform sampler2D Texture_Deluxemap;\n"
479 "uniform sampler2D Texture_Glow;\n"
481 "uniform myhvec3 LightColor;\n"
482 "uniform myhvec3 AmbientColor;\n"
483 "uniform myhvec3 DiffuseColor;\n"
484 "uniform myhvec3 SpecularColor;\n"
485 "uniform myhvec3 Color_Pants;\n"
486 "uniform myhvec3 Color_Shirt;\n"
487 "uniform myhvec3 FogColor;\n"
489 "uniform myhalf GlowScale;\n"
490 "uniform myhalf SceneBrightness;\n"
491 "#ifdef USECONTRASTBOOST\n"
492 "uniform myhalf ContrastBoostCoeff;\n"
495 "uniform float OffsetMapping_Scale;\n"
496 "uniform float OffsetMapping_Bias;\n"
497 "uniform float FogRangeRecip;\n"
499 "uniform myhalf AmbientScale;\n"
500 "uniform myhalf DiffuseScale;\n"
501 "uniform myhalf SpecularScale;\n"
502 "uniform myhalf SpecularPower;\n"
504 "#ifdef USEOFFSETMAPPING\n"
505 "vec2 OffsetMapping(vec2 TexCoord)\n"
507 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
508 " // 14 sample relief mapping: linear search and then binary search\n"
509 " // this basically steps forward a small amount repeatedly until it finds\n"
510 " // itself inside solid, then jitters forward and back using decreasing\n"
511 " // amounts to find the impact\n"
512 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
513 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
514 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
515 " vec3 RT = vec3(TexCoord, 1);\n"
516 " OffsetVector *= 0.1;\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);\n"
523 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
524 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
525 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
526 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
527 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
528 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
529 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
530 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
533 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
534 " // this basically moves forward the full distance, and then backs up based\n"
535 " // on height of samples\n"
536 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
537 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
538 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
539 " TexCoord += OffsetVector;\n"
540 " OffsetVector *= 0.333;\n"
541 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
542 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " return TexCoord;\n"
551 "#ifdef USEOFFSETMAPPING\n"
552 " // apply offsetmapping\n"
553 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
554 "#define TexCoord TexCoordOffset\n"
557 " // combine the diffuse textures (base, pants, shirt)\n"
558 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
559 "#ifdef USECOLORMAPPING\n"
560 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
566 "#ifdef MODE_LIGHTSOURCE\n"
569 " // calculate surface normal, light normal, and specular normal\n"
570 " // compute color intensity for the two textures (colormap and glossmap)\n"
571 " // scale by light color and attenuation as efficiently as possible\n"
572 " // (do as much scalar math as possible rather than vector math)\n"
573 "#ifdef USESPECULAR\n"
574 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
575 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
576 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
578 " // calculate directional shading\n"
579 " 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"
581 "#ifdef USEDIFFUSE\n"
582 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
583 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
585 " // calculate directional shading\n"
586 " 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"
588 " // calculate directionless shading\n"
589 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
593 "#ifdef USECUBEFILTER\n"
594 " // apply light cubemap filter\n"
595 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
596 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
602 "#elif defined(MODE_LIGHTDIRECTION)\n"
603 " // directional model lighting\n"
605 " // get the surface normal and light normal\n"
606 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
607 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
609 " // calculate directional shading\n"
610 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
611 "#ifdef USESPECULAR\n"
612 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
613 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
619 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
620 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
622 " // get the surface normal and light normal\n"
623 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
625 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
626 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
627 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
629 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
631 " // calculate directional shading\n"
632 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
633 "#ifdef USESPECULAR\n"
634 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
635 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
638 " // apply lightmap color\n"
639 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
642 "#else // MODE none (lightmap)\n"
643 " // apply lightmap color\n"
644 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
647 " color *= myhvec4(gl_Color);\n"
650 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
655 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
658 "#ifdef USECONTRASTBOOST\n"
659 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
661 " color.rgb *= SceneBrightness;\n"
664 " gl_FragColor = vec4(color);\n"
667 "#endif // FRAGMENT_SHADER\n"
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 const char *permutationinfo[][2] =
673 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
674 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
677 {"#define USEGLOW\n", " glow"},
678 {"#define USEFOG\n", " fog"},
679 {"#define USECOLORMAPPING\n", " colormapping"},
680 {"#define USEDIFFUSE\n", " diffuse"},
681 {"#define USECONTRASTBOOST\n", " contrastboost"},
682 {"#define USESPECULAR\n", " specular"},
683 {"#define USECUBEFILTER\n", " cubefilter"},
684 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
685 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
689 void R_GLSL_CompilePermutation(const char *filename, int permutation)
692 qboolean shaderfound;
693 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
694 int vertstrings_count;
695 int geomstrings_count;
696 int fragstrings_count;
698 const char *vertstrings_list[32+1];
699 const char *geomstrings_list[32+1];
700 const char *fragstrings_list[32+1];
701 char permutationname[256];
706 vertstrings_list[0] = "#define VERTEX_SHADER\n";
707 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
708 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
709 vertstrings_count = 1;
710 geomstrings_count = 1;
711 fragstrings_count = 1;
712 permutationname[0] = 0;
713 for (i = 0;permutationinfo[i][0];i++)
715 if (permutation & (1<<i))
717 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
718 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
719 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
720 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
724 // keep line numbers correct
725 vertstrings_list[vertstrings_count++] = "\n";
726 geomstrings_list[geomstrings_count++] = "\n";
727 fragstrings_list[fragstrings_count++] = "\n";
730 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
734 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
735 vertstrings_list[vertstrings_count++] = shaderstring;
736 geomstrings_list[geomstrings_count++] = shaderstring;
737 fragstrings_list[fragstrings_count++] = shaderstring;
740 else if (!strcmp(filename, "glsl/default.glsl"))
742 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
743 vertstrings_list[vertstrings_count++] = builtinshaderstring;
744 geomstrings_list[geomstrings_count++] = builtinshaderstring;
745 fragstrings_list[fragstrings_count++] = builtinshaderstring;
748 // clear any lists that are not needed by this shader
749 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
750 vertstrings_count = 0;
751 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
752 geomstrings_count = 0;
753 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
754 fragstrings_count = 0;
755 // compile the shader program
756 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
757 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
761 qglUseProgramObjectARB(p->program);CHECKGLERROR
762 // look up all the uniform variable names we care about, so we don't
763 // have to look them up every time we set them
764 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
765 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
766 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
767 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
768 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
769 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
770 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
771 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
772 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
773 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
774 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
775 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
776 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
777 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
778 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
779 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
780 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
781 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
782 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
783 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
784 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
785 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
786 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
787 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
788 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
789 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
790 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
791 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
792 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
793 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
794 // initialize the samplers to refer to the texture units we use
795 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
796 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
797 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
798 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
799 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
800 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
801 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
802 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
803 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
804 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
805 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
807 qglUseProgramObjectARB(0);CHECKGLERROR
810 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
812 Mem_Free(shaderstring);
815 void R_GLSL_Restart_f(void)
818 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
819 if (r_glsl_permutations[i].program)
820 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
821 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
824 void R_GLSL_DumpShader_f(void)
828 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
831 Con_Printf("failed to write to glsl/default.glsl\n");
835 FS_Print(file, "// The engine may define the following macros:\n");
836 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
837 for (i = 0;permutationinfo[i][0];i++)
838 FS_Printf(file, "// %s", permutationinfo[i][0]);
839 FS_Print(file, "\n");
840 FS_Print(file, builtinshaderstring);
843 Con_Printf("data/default.glsl written\n");
846 extern rtexture_t *r_shadow_attenuationgradienttexture;
847 extern rtexture_t *r_shadow_attenuation2dtexture;
848 extern rtexture_t *r_shadow_attenuation3dtexture;
849 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
851 // select a permutation of the lighting shader appropriate to this
852 // combination of texture, entity, light source, and fogging, only use the
853 // minimum features necessary to avoid wasting rendering time in the
854 // fragment shader on features that are not being used
855 const char *shaderfilename = NULL;
856 unsigned int permutation = 0;
857 r_glsl_permutation = NULL;
858 // TODO: implement geometry-shader based shadow volumes someday
859 if (rsurface.rtlight)
862 shaderfilename = "glsl/default.glsl";
863 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
865 permutation |= SHADERPERMUTATION_CUBEFILTER;
866 if (diffusescale > 0)
867 permutation |= SHADERPERMUTATION_DIFFUSE;
868 if (specularscale > 0)
869 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
870 if (r_refdef.fogenabled)
871 permutation |= SHADERPERMUTATION_FOG;
872 if (rsurface.texture->colormapping)
873 permutation |= SHADERPERMUTATION_COLORMAPPING;
874 if (r_glsl_offsetmapping.integer)
876 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
877 if (r_glsl_offsetmapping_reliefmapping.integer)
878 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
880 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
881 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
883 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
885 // bright unshaded geometry
886 shaderfilename = "glsl/default.glsl";
887 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
888 if (rsurface.texture->currentskinframe->glow)
889 permutation |= SHADERPERMUTATION_GLOW;
890 if (r_refdef.fogenabled)
891 permutation |= SHADERPERMUTATION_FOG;
892 if (rsurface.texture->colormapping)
893 permutation |= SHADERPERMUTATION_COLORMAPPING;
894 if (r_glsl_offsetmapping.integer)
896 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
897 if (r_glsl_offsetmapping_reliefmapping.integer)
898 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
900 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
901 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
903 else if (modellighting)
905 // directional model lighting
906 shaderfilename = "glsl/default.glsl";
907 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
908 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
909 if (rsurface.texture->currentskinframe->glow)
910 permutation |= SHADERPERMUTATION_GLOW;
911 if (specularscale > 0)
912 permutation |= SHADERPERMUTATION_SPECULAR;
913 if (r_refdef.fogenabled)
914 permutation |= SHADERPERMUTATION_FOG;
915 if (rsurface.texture->colormapping)
916 permutation |= SHADERPERMUTATION_COLORMAPPING;
917 if (r_glsl_offsetmapping.integer)
919 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
920 if (r_glsl_offsetmapping_reliefmapping.integer)
921 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
923 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
924 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
929 shaderfilename = "glsl/default.glsl";
930 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
931 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
933 // deluxemapping (light direction texture)
934 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
935 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
937 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
938 if (specularscale > 0)
939 permutation |= SHADERPERMUTATION_SPECULAR;
941 else if (r_glsl_deluxemapping.integer >= 2)
943 // fake deluxemapping (uniform light direction in tangentspace)
944 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
945 if (specularscale > 0)
946 permutation |= SHADERPERMUTATION_SPECULAR;
950 // ordinary lightmapping
953 if (rsurface.texture->currentskinframe->glow)
954 permutation |= SHADERPERMUTATION_GLOW;
955 if (r_refdef.fogenabled)
956 permutation |= SHADERPERMUTATION_FOG;
957 if (rsurface.texture->colormapping)
958 permutation |= SHADERPERMUTATION_COLORMAPPING;
959 if (r_glsl_offsetmapping.integer)
961 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
962 if (r_glsl_offsetmapping_reliefmapping.integer)
963 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
965 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
966 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
968 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
970 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
971 R_GLSL_CompilePermutation(shaderfilename, permutation);
972 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
974 // remove features until we find a valid permutation
976 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
979 return 0; // no bit left to clear
980 // reduce i more quickly whenever it would not remove any bits
981 if (!(permutation & i))
984 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
985 R_GLSL_CompilePermutation(shaderfilename, permutation);
986 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
991 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
993 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
994 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
995 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
997 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
998 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
999 if (permutation & SHADERPERMUTATION_DIFFUSE)
1001 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1002 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1003 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1004 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1008 // ambient only is simpler
1009 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1010 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1011 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1012 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1015 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1017 if (r_glsl_permutation->loc_AmbientColor >= 0)
1018 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1019 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1020 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1021 if (r_glsl_permutation->loc_SpecularColor >= 0)
1022 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1023 if (r_glsl_permutation->loc_LightDir >= 0)
1024 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1028 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1029 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1030 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1032 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
1033 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1034 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1035 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1036 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1037 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1038 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1039 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1040 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1041 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1042 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1043 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1044 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1046 // The formula used is actually:
1047 // color.rgb *= SceneBrightness;
1048 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1049 // I simplify that to
1050 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1051 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1053 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1054 // and do [[calculations]] here in the engine
1055 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1056 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1059 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1060 if (r_glsl_permutation->loc_FogColor >= 0)
1062 // additive passes are only darkened by fog, not tinted
1063 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1064 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1066 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1068 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1069 if (r_glsl_permutation->loc_Color_Pants >= 0)
1071 if (rsurface.texture->currentskinframe->pants)
1072 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1074 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1076 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1078 if (rsurface.texture->currentskinframe->shirt)
1079 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1081 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1083 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1084 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1085 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1090 void R_SwitchSurfaceShader(int permutation)
1092 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1094 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1096 qglUseProgramObjectARB(r_glsl_permutation->program);
1101 #define SKINFRAME_HASH 1024
1105 int loadsequence; // incremented each level change
1106 memexpandablearray_t array;
1107 skinframe_t *hash[SKINFRAME_HASH];
1111 void R_SkinFrame_PrepareForPurge(void)
1113 r_skinframe.loadsequence++;
1114 // wrap it without hitting zero
1115 if (r_skinframe.loadsequence >= 200)
1116 r_skinframe.loadsequence = 1;
1119 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1123 // mark the skinframe as used for the purging code
1124 skinframe->loadsequence = r_skinframe.loadsequence;
1127 void R_SkinFrame_Purge(void)
1131 for (i = 0;i < SKINFRAME_HASH;i++)
1133 for (s = r_skinframe.hash[i];s;s = s->next)
1135 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1137 if (s->base == r_texture_notexture) s->base = NULL;
1138 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1139 if (s->merged == s->base) s->merged = NULL;
1140 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1141 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1142 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1143 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1144 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1145 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1146 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1147 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1148 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1149 s->loadsequence = 0;
1155 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1159 char basename[MAX_QPATH];
1161 Image_StripImageExtension(name, basename, sizeof(basename));
1163 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1164 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1165 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1171 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1172 memset(item, 0, sizeof(*item));
1173 strlcpy(item->basename, basename, sizeof(item->basename));
1174 item->textureflags = textureflags;
1175 item->comparewidth = comparewidth;
1176 item->compareheight = compareheight;
1177 item->comparecrc = comparecrc;
1178 item->next = r_skinframe.hash[hashindex];
1179 r_skinframe.hash[hashindex] = item;
1181 R_SkinFrame_MarkUsed(item);
1185 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1187 // FIXME: it should be possible to disable loading various layers using
1188 // cvars, to prevent wasted loading time and memory usage if the user does
1190 qboolean loadnormalmap = true;
1191 qboolean loadgloss = true;
1192 qboolean loadpantsandshirt = true;
1193 qboolean loadglow = true;
1195 unsigned char *pixels;
1196 unsigned char *bumppixels;
1197 unsigned char *basepixels = NULL;
1198 int basepixels_width;
1199 int basepixels_height;
1200 skinframe_t *skinframe;
1202 if (cls.state == ca_dedicated)
1205 // return an existing skinframe if already loaded
1206 // if loading of the first image fails, don't make a new skinframe as it
1207 // would cause all future lookups of this to be missing
1208 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1209 if (skinframe && skinframe->base)
1212 basepixels = loadimagepixels(name, complain, 0, 0);
1213 if (basepixels == NULL)
1216 // we've got some pixels to store, so really allocate this new texture now
1218 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1219 skinframe->stain = NULL;
1220 skinframe->merged = NULL;
1221 skinframe->base = r_texture_notexture;
1222 skinframe->pants = NULL;
1223 skinframe->shirt = NULL;
1224 skinframe->nmap = r_texture_blanknormalmap;
1225 skinframe->gloss = NULL;
1226 skinframe->glow = NULL;
1227 skinframe->fog = NULL;
1229 basepixels_width = image_width;
1230 basepixels_height = image_height;
1231 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1233 if (textureflags & TEXF_ALPHA)
1235 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1236 if (basepixels[j] < 255)
1238 if (j < basepixels_width * basepixels_height * 4)
1240 // has transparent pixels
1241 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1242 for (j = 0;j < image_width * image_height * 4;j += 4)
1247 pixels[j+3] = basepixels[j+3];
1249 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1254 // _norm is the name used by tenebrae and has been adopted as standard
1257 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1259 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1263 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1265 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1266 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1267 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1269 Mem_Free(bumppixels);
1271 else if (r_shadow_bumpscale_basetexture.value > 0)
1273 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1274 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1275 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1279 // _luma is supported for tenebrae compatibility
1280 // (I think it's a very stupid name, but oh well)
1281 // _glow is the preferred name
1282 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;}
1283 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;}
1284 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;}
1285 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;}
1288 Mem_Free(basepixels);
1293 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)
1298 for (i = 0;i < width*height;i++)
1299 if (((unsigned char *)&palette[in[i]])[3] > 0)
1301 if (i == width*height)
1304 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1307 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)
1310 unsigned char *temp1, *temp2;
1311 skinframe_t *skinframe;
1313 if (cls.state == ca_dedicated)
1316 // if already loaded just return it, otherwise make a new skinframe
1317 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1318 if (skinframe && skinframe->base)
1321 skinframe->stain = NULL;
1322 skinframe->merged = NULL;
1323 skinframe->base = r_texture_notexture;
1324 skinframe->pants = NULL;
1325 skinframe->shirt = NULL;
1326 skinframe->nmap = r_texture_blanknormalmap;
1327 skinframe->gloss = NULL;
1328 skinframe->glow = NULL;
1329 skinframe->fog = NULL;
1331 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1335 if (bitsperpixel == 32)
1337 if (r_shadow_bumpscale_basetexture.value > 0)
1339 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1340 temp2 = temp1 + width * height * 4;
1341 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1342 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1345 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1346 if (textureflags & TEXF_ALPHA)
1348 for (i = 3;i < width * height * 4;i += 4)
1349 if (skindata[i] < 255)
1351 if (i < width * height * 4)
1353 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1354 memcpy(fogpixels, skindata, width * height * 4);
1355 for (i = 0;i < width * height * 4;i += 4)
1356 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1357 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1358 Mem_Free(fogpixels);
1362 else if (bitsperpixel == 8)
1364 if (r_shadow_bumpscale_basetexture.value > 0)
1366 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1367 temp2 = temp1 + width * height * 4;
1368 if (bitsperpixel == 32)
1369 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1372 // use either a custom palette or the quake palette
1373 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1374 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1376 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1379 // use either a custom palette, or the quake palette
1380 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
1381 if (!palette && loadglowtexture)
1382 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1383 if (!palette && loadpantsandshirt)
1385 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1386 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1388 if (skinframe->pants || skinframe->shirt)
1389 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1390 if (textureflags & TEXF_ALPHA)
1392 // if not using a custom alphapalette, use the quake one
1394 alphapalette = palette_alpha;
1395 for (i = 0;i < width * height;i++)
1396 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1398 if (i < width * height)
1399 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1406 skinframe_t *R_SkinFrame_LoadMissing(void)
1408 skinframe_t *skinframe;
1410 if (cls.state == ca_dedicated)
1413 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1414 skinframe->stain = NULL;
1415 skinframe->merged = NULL;
1416 skinframe->base = r_texture_notexture;
1417 skinframe->pants = NULL;
1418 skinframe->shirt = NULL;
1419 skinframe->nmap = r_texture_blanknormalmap;
1420 skinframe->gloss = NULL;
1421 skinframe->glow = NULL;
1422 skinframe->fog = NULL;
1427 void gl_main_start(void)
1432 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1433 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1435 alpha = 1 - exp(r / ((double)x*(double)x));
1436 if (x == FOGMASKTABLEWIDTH - 1)
1438 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1441 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1442 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1444 // set up r_skinframe loading system for textures
1445 memset(&r_skinframe, 0, sizeof(r_skinframe));
1446 r_skinframe.loadsequence = 1;
1447 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1449 r_main_texturepool = R_AllocTexturePool();
1450 R_BuildBlankTextures();
1452 if (gl_texturecubemap)
1455 R_BuildNormalizationCube();
1457 R_BuildFogTexture();
1458 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1459 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1460 memset(&r_svbsp, 0, sizeof (r_svbsp));
1463 void gl_main_shutdown(void)
1465 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1466 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1468 // clear out the r_skinframe state
1469 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1470 memset(&r_skinframe, 0, sizeof(r_skinframe));
1473 Mem_Free(r_svbsp.nodes);
1474 memset(&r_svbsp, 0, sizeof (r_svbsp));
1475 R_FreeTexturePool(&r_main_texturepool);
1476 r_texture_blanknormalmap = NULL;
1477 r_texture_white = NULL;
1478 r_texture_black = NULL;
1479 r_texture_whitecube = NULL;
1480 r_texture_normalizationcube = NULL;
1481 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1485 extern void CL_ParseEntityLump(char *entitystring);
1486 void gl_main_newmap(void)
1488 // FIXME: move this code to client
1490 char *entities, entname[MAX_QPATH];
1493 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1494 l = (int)strlen(entname) - 4;
1495 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1497 memcpy(entname + l, ".ent", 5);
1498 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1500 CL_ParseEntityLump(entities);
1505 if (cl.worldmodel->brush.entities)
1506 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1510 void GL_Main_Init(void)
1512 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1514 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1515 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1516 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1517 if (gamemode == GAME_NEHAHRA)
1519 Cvar_RegisterVariable (&gl_fogenable);
1520 Cvar_RegisterVariable (&gl_fogdensity);
1521 Cvar_RegisterVariable (&gl_fogred);
1522 Cvar_RegisterVariable (&gl_foggreen);
1523 Cvar_RegisterVariable (&gl_fogblue);
1524 Cvar_RegisterVariable (&gl_fogstart);
1525 Cvar_RegisterVariable (&gl_fogend);
1527 Cvar_RegisterVariable(&r_depthfirst);
1528 Cvar_RegisterVariable(&r_nearclip);
1529 Cvar_RegisterVariable(&r_showbboxes);
1530 Cvar_RegisterVariable(&r_showsurfaces);
1531 Cvar_RegisterVariable(&r_showtris);
1532 Cvar_RegisterVariable(&r_shownormals);
1533 Cvar_RegisterVariable(&r_showlighting);
1534 Cvar_RegisterVariable(&r_showshadowvolumes);
1535 Cvar_RegisterVariable(&r_showcollisionbrushes);
1536 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1537 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1538 Cvar_RegisterVariable(&r_showdisabledepthtest);
1539 Cvar_RegisterVariable(&r_drawportals);
1540 Cvar_RegisterVariable(&r_drawentities);
1541 Cvar_RegisterVariable(&r_cullentities_trace);
1542 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1543 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1544 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1545 Cvar_RegisterVariable(&r_drawviewmodel);
1546 Cvar_RegisterVariable(&r_speeds);
1547 Cvar_RegisterVariable(&r_fullbrights);
1548 Cvar_RegisterVariable(&r_wateralpha);
1549 Cvar_RegisterVariable(&r_dynamic);
1550 Cvar_RegisterVariable(&r_fullbright);
1551 Cvar_RegisterVariable(&r_shadows);
1552 Cvar_RegisterVariable(&r_shadows_throwdistance);
1553 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1554 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1555 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1556 Cvar_RegisterVariable(&r_textureunits);
1557 Cvar_RegisterVariable(&r_glsl);
1558 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1559 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1560 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1561 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1562 Cvar_RegisterVariable(&r_lerpsprites);
1563 Cvar_RegisterVariable(&r_lerpmodels);
1564 Cvar_RegisterVariable(&r_waterscroll);
1565 Cvar_RegisterVariable(&r_bloom);
1566 Cvar_RegisterVariable(&r_bloom_colorscale);
1567 Cvar_RegisterVariable(&r_bloom_brighten);
1568 Cvar_RegisterVariable(&r_bloom_blur);
1569 Cvar_RegisterVariable(&r_bloom_resolution);
1570 Cvar_RegisterVariable(&r_bloom_colorexponent);
1571 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1572 Cvar_RegisterVariable(&r_hdr);
1573 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1574 Cvar_RegisterVariable(&r_glsl_contrastboost);
1575 Cvar_RegisterVariable(&r_hdr_glowintensity);
1576 Cvar_RegisterVariable(&r_hdr_range);
1577 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1578 Cvar_RegisterVariable(&developer_texturelogging);
1579 Cvar_RegisterVariable(&gl_lightmaps);
1580 Cvar_RegisterVariable(&r_test);
1581 Cvar_RegisterVariable(&r_batchmode);
1582 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1583 Cvar_SetValue("r_fullbrights", 0);
1584 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1587 extern void R_Textures_Init(void);
1588 extern void GL_Draw_Init(void);
1589 extern void GL_Main_Init(void);
1590 extern void R_Shadow_Init(void);
1591 extern void R_Sky_Init(void);
1592 extern void GL_Surf_Init(void);
1593 extern void R_Light_Init(void);
1594 extern void R_Particles_Init(void);
1595 extern void R_Explosion_Init(void);
1596 extern void gl_backend_init(void);
1597 extern void Sbar_Init(void);
1598 extern void R_LightningBeams_Init(void);
1599 extern void Mod_RenderInit(void);
1601 void Render_Init(void)
1614 R_LightningBeams_Init();
1623 extern char *ENGINE_EXTENSIONS;
1626 VID_CheckExtensions();
1628 // LordHavoc: report supported extensions
1629 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1631 // clear to black (loading plaque will be seen over this)
1633 qglClearColor(0,0,0,1);CHECKGLERROR
1634 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1637 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1641 for (i = 0;i < 4;i++)
1643 p = r_view.frustum + i;
1648 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1652 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1656 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1660 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1664 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1668 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1672 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1676 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1684 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1688 for (i = 0;i < numplanes;i++)
1695 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1699 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1703 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1707 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1711 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1715 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1719 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1723 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1731 //==================================================================================
1733 static void R_UpdateEntityLighting(entity_render_t *ent)
1735 vec3_t tempdiffusenormal;
1737 // fetch the lighting from the worldmodel data
1738 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));
1739 VectorClear(ent->modellight_diffuse);
1740 VectorClear(tempdiffusenormal);
1741 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1744 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1745 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1748 VectorSet(ent->modellight_ambient, 1, 1, 1);
1750 // move the light direction into modelspace coordinates for lighting code
1751 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1752 if(VectorLength2(ent->modellight_lightdir) > 0)
1754 VectorNormalize(ent->modellight_lightdir);
1758 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1761 // scale ambient and directional light contributions according to rendering variables
1762 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1763 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1764 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1765 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1766 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1767 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1770 static void R_View_UpdateEntityVisible (void)
1773 entity_render_t *ent;
1775 if (!r_drawentities.integer)
1778 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1779 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1781 // worldmodel can check visibility
1782 for (i = 0;i < r_refdef.numentities;i++)
1784 ent = r_refdef.entities[i];
1785 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));
1787 if(r_cullentities_trace.integer)
1789 for (i = 0;i < r_refdef.numentities;i++)
1791 ent = r_refdef.entities[i];
1792 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1794 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1795 ent->last_trace_visibility = realtime;
1796 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1797 r_viewcache.entityvisible[i] = 0;
1804 // no worldmodel or it can't check visibility
1805 for (i = 0;i < r_refdef.numentities;i++)
1807 ent = r_refdef.entities[i];
1808 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1812 // update entity lighting (even on hidden entities for r_shadows)
1813 for (i = 0;i < r_refdef.numentities;i++)
1814 R_UpdateEntityLighting(r_refdef.entities[i]);
1817 // only used if skyrendermasked, and normally returns false
1818 int R_DrawBrushModelsSky (void)
1821 entity_render_t *ent;
1823 if (!r_drawentities.integer)
1827 for (i = 0;i < r_refdef.numentities;i++)
1829 if (!r_viewcache.entityvisible[i])
1831 ent = r_refdef.entities[i];
1832 if (!ent->model || !ent->model->DrawSky)
1834 ent->model->DrawSky(ent);
1840 void R_DrawNoModel(entity_render_t *ent);
1841 void R_DrawModels(void)
1844 entity_render_t *ent;
1846 if (!r_drawentities.integer)
1849 for (i = 0;i < r_refdef.numentities;i++)
1851 if (!r_viewcache.entityvisible[i])
1853 ent = r_refdef.entities[i];
1854 r_refdef.stats.entities++;
1855 if (ent->model && ent->model->Draw != NULL)
1856 ent->model->Draw(ent);
1862 void R_DrawModelsDepth(void)
1865 entity_render_t *ent;
1867 if (!r_drawentities.integer)
1870 for (i = 0;i < r_refdef.numentities;i++)
1872 if (!r_viewcache.entityvisible[i])
1874 ent = r_refdef.entities[i];
1875 r_refdef.stats.entities++;
1876 if (ent->model && ent->model->DrawDepth != NULL)
1877 ent->model->DrawDepth(ent);
1881 static void R_View_SetFrustum(void)
1883 double slopex, slopey;
1885 // break apart the view matrix into vectors for various purposes
1886 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1887 VectorNegate(r_view.left, r_view.right);
1890 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1891 r_view.frustum[0].normal[1] = 0 - 0;
1892 r_view.frustum[0].normal[2] = -1 - 0;
1893 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1894 r_view.frustum[1].normal[1] = 0 + 0;
1895 r_view.frustum[1].normal[2] = -1 + 0;
1896 r_view.frustum[2].normal[0] = 0 - 0;
1897 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1898 r_view.frustum[2].normal[2] = -1 - 0;
1899 r_view.frustum[3].normal[0] = 0 + 0;
1900 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1901 r_view.frustum[3].normal[2] = -1 + 0;
1905 zNear = r_refdef.nearclip;
1906 nudge = 1.0 - 1.0 / (1<<23);
1907 r_view.frustum[4].normal[0] = 0 - 0;
1908 r_view.frustum[4].normal[1] = 0 - 0;
1909 r_view.frustum[4].normal[2] = -1 - -nudge;
1910 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1911 r_view.frustum[5].normal[0] = 0 + 0;
1912 r_view.frustum[5].normal[1] = 0 + 0;
1913 r_view.frustum[5].normal[2] = -1 + -nudge;
1914 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1920 r_view.frustum[0].normal[0] = m[3] - m[0];
1921 r_view.frustum[0].normal[1] = m[7] - m[4];
1922 r_view.frustum[0].normal[2] = m[11] - m[8];
1923 r_view.frustum[0].dist = m[15] - m[12];
1925 r_view.frustum[1].normal[0] = m[3] + m[0];
1926 r_view.frustum[1].normal[1] = m[7] + m[4];
1927 r_view.frustum[1].normal[2] = m[11] + m[8];
1928 r_view.frustum[1].dist = m[15] + m[12];
1930 r_view.frustum[2].normal[0] = m[3] - m[1];
1931 r_view.frustum[2].normal[1] = m[7] - m[5];
1932 r_view.frustum[2].normal[2] = m[11] - m[9];
1933 r_view.frustum[2].dist = m[15] - m[13];
1935 r_view.frustum[3].normal[0] = m[3] + m[1];
1936 r_view.frustum[3].normal[1] = m[7] + m[5];
1937 r_view.frustum[3].normal[2] = m[11] + m[9];
1938 r_view.frustum[3].dist = m[15] + m[13];
1940 r_view.frustum[4].normal[0] = m[3] - m[2];
1941 r_view.frustum[4].normal[1] = m[7] - m[6];
1942 r_view.frustum[4].normal[2] = m[11] - m[10];
1943 r_view.frustum[4].dist = m[15] - m[14];
1945 r_view.frustum[5].normal[0] = m[3] + m[2];
1946 r_view.frustum[5].normal[1] = m[7] + m[6];
1947 r_view.frustum[5].normal[2] = m[11] + m[10];
1948 r_view.frustum[5].dist = m[15] + m[14];
1953 if (r_view.useperspective)
1955 slopex = 1.0 / r_view.frustum_x;
1956 slopey = 1.0 / r_view.frustum_y;
1957 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1958 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1959 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1960 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1961 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1963 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1964 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1965 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1966 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1967 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1969 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1970 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1971 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1972 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1973 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1977 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1978 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
1979 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1980 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
1981 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1982 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1983 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1984 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
1985 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
1986 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1989 PlaneClassify(&r_view.frustum[0]);
1990 PlaneClassify(&r_view.frustum[1]);
1991 PlaneClassify(&r_view.frustum[2]);
1992 PlaneClassify(&r_view.frustum[3]);
1993 PlaneClassify(&r_view.frustum[4]);
1995 // LordHavoc: note to all quake engine coders, Quake had a special case
1996 // for 90 degrees which assumed a square view (wrong), so I removed it,
1997 // Quake2 has it disabled as well.
1999 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2000 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2001 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2002 //PlaneClassify(&frustum[0]);
2004 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2005 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2006 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2007 //PlaneClassify(&frustum[1]);
2009 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2010 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2011 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2012 //PlaneClassify(&frustum[2]);
2014 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2015 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2016 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2017 //PlaneClassify(&frustum[3]);
2020 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2021 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2022 //PlaneClassify(&frustum[4]);
2025 void R_View_Update(void)
2027 R_View_SetFrustum();
2028 R_View_WorldVisibility();
2029 R_View_UpdateEntityVisible();
2032 void R_SetupView(const matrix4x4_t *matrix)
2034 if (!r_view.useperspective)
2035 GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2036 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2037 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2039 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2041 GL_SetupView_Orientation_FromEntity(matrix);
2044 void R_ResetViewRendering2D(void)
2046 if (gl_support_fragment_shader)
2048 qglUseProgramObjectARB(0);CHECKGLERROR
2053 // GL is weird because it's bottom to top, r_view.y is top to bottom
2054 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2055 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2056 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2057 GL_Color(1, 1, 1, 1);
2058 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2059 GL_BlendFunc(GL_ONE, GL_ZERO);
2060 GL_AlphaTest(false);
2061 GL_ScissorTest(false);
2062 GL_DepthMask(false);
2063 GL_DepthRange(0, 1);
2064 GL_DepthTest(false);
2065 R_Mesh_Matrix(&identitymatrix);
2066 R_Mesh_ResetTextureState();
2067 GL_PolygonOffset(0, 0);
2068 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2069 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2070 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2071 qglStencilMask(~0);CHECKGLERROR
2072 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2073 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2074 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2077 void R_ResetViewRendering3D(void)
2079 if (gl_support_fragment_shader)
2081 qglUseProgramObjectARB(0);CHECKGLERROR
2086 // GL is weird because it's bottom to top, r_view.y is top to bottom
2087 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2088 R_SetupView(&r_view.matrix);
2089 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2090 GL_Color(1, 1, 1, 1);
2091 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2092 GL_BlendFunc(GL_ONE, GL_ZERO);
2093 GL_AlphaTest(false);
2094 GL_ScissorTest(true);
2096 GL_DepthRange(0, 1);
2098 R_Mesh_Matrix(&identitymatrix);
2099 R_Mesh_ResetTextureState();
2100 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2101 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2102 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2103 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2104 qglStencilMask(~0);CHECKGLERROR
2105 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2106 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2107 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2111 R_Bloom_SetupShader(
2113 "// written by Forest 'LordHavoc' Hale\n"
2115 "// common definitions between vertex shader and fragment shader:\n"
2117 "#ifdef __GLSL_CG_DATA_TYPES\n"
2118 "#define myhalf half\n"
2119 "#define myhvec2 hvec2\n"
2120 "#define myhvec3 hvec3\n"
2121 "#define myhvec4 hvec4\n"
2123 "#define myhalf float\n"
2124 "#define myhvec2 vec2\n"
2125 "#define myhvec3 vec3\n"
2126 "#define myhvec4 vec4\n"
2129 "varying vec2 ScreenTexCoord;\n"
2130 "varying vec2 BloomTexCoord;\n"
2135 "// vertex shader specific:\n"
2136 "#ifdef VERTEX_SHADER\n"
2140 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2141 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2142 " // transform vertex to camera space, using ftransform to match non-VS\n"
2144 " gl_Position = ftransform();\n"
2147 "#endif // VERTEX_SHADER\n"
2152 "// fragment shader specific:\n"
2153 "#ifdef FRAGMENT_SHADER\n"
2158 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2159 " for (x = -BLUR_X;x <= BLUR_X;x++)
2160 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2161 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2162 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2163 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2165 " gl_FragColor = vec4(color);\n"
2168 "#endif // FRAGMENT_SHADER\n"
2171 void R_RenderScene(void);
2173 void R_Bloom_StartFrame(void)
2175 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2177 // set bloomwidth and bloomheight to the bloom resolution that will be
2178 // used (often less than the screen resolution for faster rendering)
2179 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2180 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2181 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2183 // calculate desired texture sizes
2184 if (gl_support_arb_texture_non_power_of_two)
2186 screentexturewidth = r_view.width;
2187 screentextureheight = r_view.height;
2188 bloomtexturewidth = r_bloomstate.bloomwidth;
2189 bloomtextureheight = r_bloomstate.bloomheight;
2193 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2194 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2195 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2196 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2201 screentexturewidth = screentextureheight = 0;
2203 else if (r_bloom.integer)
2208 screentexturewidth = screentextureheight = 0;
2209 bloomtexturewidth = bloomtextureheight = 0;
2212 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)
2214 // can't use bloom if the parameters are too weird
2215 // can't use bloom if the card does not support the texture size
2216 if (r_bloomstate.texture_screen)
2217 R_FreeTexture(r_bloomstate.texture_screen);
2218 if (r_bloomstate.texture_bloom)
2219 R_FreeTexture(r_bloomstate.texture_bloom);
2220 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2224 r_bloomstate.enabled = true;
2225 r_bloomstate.hdr = r_hdr.integer != 0;
2227 // allocate textures as needed
2228 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2230 if (r_bloomstate.texture_screen)
2231 R_FreeTexture(r_bloomstate.texture_screen);
2232 r_bloomstate.texture_screen = NULL;
2233 r_bloomstate.screentexturewidth = screentexturewidth;
2234 r_bloomstate.screentextureheight = screentextureheight;
2235 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2236 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);
2238 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2240 if (r_bloomstate.texture_bloom)
2241 R_FreeTexture(r_bloomstate.texture_bloom);
2242 r_bloomstate.texture_bloom = NULL;
2243 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2244 r_bloomstate.bloomtextureheight = bloomtextureheight;
2245 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2246 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);
2249 // set up a texcoord array for the full resolution screen image
2250 // (we have to keep this around to copy back during final render)
2251 r_bloomstate.screentexcoord2f[0] = 0;
2252 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2253 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2254 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2255 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2256 r_bloomstate.screentexcoord2f[5] = 0;
2257 r_bloomstate.screentexcoord2f[6] = 0;
2258 r_bloomstate.screentexcoord2f[7] = 0;
2260 // set up a texcoord array for the reduced resolution bloom image
2261 // (which will be additive blended over the screen image)
2262 r_bloomstate.bloomtexcoord2f[0] = 0;
2263 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2264 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2265 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2266 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2267 r_bloomstate.bloomtexcoord2f[5] = 0;
2268 r_bloomstate.bloomtexcoord2f[6] = 0;
2269 r_bloomstate.bloomtexcoord2f[7] = 0;
2272 void R_Bloom_CopyScreenTexture(float colorscale)
2274 r_refdef.stats.bloom++;
2276 R_ResetViewRendering2D();
2277 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2278 R_Mesh_ColorPointer(NULL, 0, 0);
2279 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2280 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2282 // copy view into the screen texture
2283 GL_ActiveTexture(0);
2285 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
2286 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2288 // now scale it down to the bloom texture size
2290 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2291 GL_BlendFunc(GL_ONE, GL_ZERO);
2292 GL_Color(colorscale, colorscale, colorscale, 1);
2293 // TODO: optimize with multitexture or GLSL
2294 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2295 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2297 // we now have a bloom image in the framebuffer
2298 // copy it into the bloom image texture for later processing
2299 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2300 GL_ActiveTexture(0);
2302 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
2303 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2306 void R_Bloom_CopyHDRTexture(void)
2308 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2309 GL_ActiveTexture(0);
2311 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
2312 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2315 void R_Bloom_MakeTexture(void)
2318 float xoffset, yoffset, r, brighten;
2320 r_refdef.stats.bloom++;
2322 R_ResetViewRendering2D();
2323 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2324 R_Mesh_ColorPointer(NULL, 0, 0);
2326 // we have a bloom image in the framebuffer
2328 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2330 for (x = 1;x < r_bloom_colorexponent.value;)
2333 r = bound(0, r_bloom_colorexponent.value / x, 1);
2334 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2335 GL_Color(r, r, r, 1);
2336 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2337 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2338 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2339 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2341 // copy the vertically blurred bloom view to a texture
2342 GL_ActiveTexture(0);
2344 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
2345 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2348 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2349 brighten = r_bloom_brighten.value;
2351 brighten *= r_hdr_range.value;
2352 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2353 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2355 for (dir = 0;dir < 2;dir++)
2357 // blend on at multiple vertical offsets to achieve a vertical blur
2358 // TODO: do offset blends using GLSL
2359 GL_BlendFunc(GL_ONE, GL_ZERO);
2360 for (x = -range;x <= range;x++)
2362 if (!dir){xoffset = 0;yoffset = x;}
2363 else {xoffset = x;yoffset = 0;}
2364 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2365 yoffset /= (float)r_bloomstate.bloomtextureheight;
2366 // compute a texcoord array with the specified x and y offset
2367 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2368 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2369 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2370 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2371 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2372 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2373 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2374 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2375 // this r value looks like a 'dot' particle, fading sharply to
2376 // black at the edges
2377 // (probably not realistic but looks good enough)
2378 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2379 //r = (dir ? 1.0f : brighten)/(range*2+1);
2380 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2381 GL_Color(r, r, r, 1);
2382 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2383 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2384 GL_BlendFunc(GL_ONE, GL_ONE);
2387 // copy the vertically blurred bloom view to a texture
2388 GL_ActiveTexture(0);
2390 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
2391 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2394 // apply subtract last
2395 // (just like it would be in a GLSL shader)
2396 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2398 GL_BlendFunc(GL_ONE, GL_ZERO);
2399 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2400 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2401 GL_Color(1, 1, 1, 1);
2402 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2403 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2405 GL_BlendFunc(GL_ONE, GL_ONE);
2406 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2407 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2408 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2409 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2410 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2411 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2412 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2414 // copy the darkened bloom view to a texture
2415 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2416 GL_ActiveTexture(0);
2418 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
2419 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2423 void R_HDR_RenderBloomTexture(void)
2425 int oldwidth, oldheight;
2427 oldwidth = r_view.width;
2428 oldheight = r_view.height;
2429 r_view.width = r_bloomstate.bloomwidth;
2430 r_view.height = r_bloomstate.bloomheight;
2432 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2433 // TODO: add exposure compensation features
2434 // TODO: add fp16 framebuffer support
2436 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2438 r_view.colorscale /= r_hdr_range.value;
2441 R_ResetViewRendering2D();
2443 R_Bloom_CopyHDRTexture();
2444 R_Bloom_MakeTexture();
2446 R_ResetViewRendering3D();
2449 if (r_timereport_active)
2450 R_TimeReport("clear");
2453 // restore the view settings
2454 r_view.width = oldwidth;
2455 r_view.height = oldheight;
2458 static void R_BlendView(void)
2460 if (r_bloomstate.enabled && r_bloomstate.hdr)
2462 // render high dynamic range bloom effect
2463 // the bloom texture was made earlier this render, so we just need to
2464 // blend it onto the screen...
2465 R_ResetViewRendering2D();
2466 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2467 R_Mesh_ColorPointer(NULL, 0, 0);
2468 GL_Color(1, 1, 1, 1);
2469 GL_BlendFunc(GL_ONE, GL_ONE);
2470 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2471 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2472 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2473 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2475 else if (r_bloomstate.enabled)
2477 // render simple bloom effect
2478 // copy the screen and shrink it and darken it for the bloom process
2479 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2480 // make the bloom texture
2481 R_Bloom_MakeTexture();
2482 // put the original screen image back in place and blend the bloom
2484 R_ResetViewRendering2D();
2485 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2486 R_Mesh_ColorPointer(NULL, 0, 0);
2487 GL_Color(1, 1, 1, 1);
2488 GL_BlendFunc(GL_ONE, GL_ZERO);
2489 // do both in one pass if possible
2490 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2491 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2492 if (r_textureunits.integer >= 2 && gl_combine.integer)
2494 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2495 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2496 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2500 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2501 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2502 // now blend on the bloom texture
2503 GL_BlendFunc(GL_ONE, GL_ONE);
2504 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2505 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2507 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2508 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2510 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2512 // apply a color tint to the whole view
2513 R_ResetViewRendering2D();
2514 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2515 R_Mesh_ColorPointer(NULL, 0, 0);
2516 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2517 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2518 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2522 void R_RenderScene(void);
2524 matrix4x4_t r_waterscrollmatrix;
2526 void R_UpdateVariables(void)
2530 r_refdef.farclip = 4096;
2531 if (r_refdef.worldmodel)
2532 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2533 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2535 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2536 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2537 r_refdef.polygonfactor = 0;
2538 r_refdef.polygonoffset = 0;
2539 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2540 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2542 r_refdef.rtworld = r_shadow_realtime_world.integer;
2543 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2544 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2545 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2546 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2547 if (r_showsurfaces.integer)
2549 r_refdef.rtworld = false;
2550 r_refdef.rtworldshadows = false;
2551 r_refdef.rtdlight = false;
2552 r_refdef.rtdlightshadows = false;
2553 r_refdef.lightmapintensity = 0;
2556 if (gamemode == GAME_NEHAHRA)
2558 if (gl_fogenable.integer)
2560 r_refdef.oldgl_fogenable = true;
2561 r_refdef.fog_density = gl_fogdensity.value;
2562 r_refdef.fog_red = gl_fogred.value;
2563 r_refdef.fog_green = gl_foggreen.value;
2564 r_refdef.fog_blue = gl_fogblue.value;
2566 else if (r_refdef.oldgl_fogenable)
2568 r_refdef.oldgl_fogenable = false;
2569 r_refdef.fog_density = 0;
2570 r_refdef.fog_red = 0;
2571 r_refdef.fog_green = 0;
2572 r_refdef.fog_blue = 0;
2575 if (r_refdef.fog_density)
2577 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2578 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2579 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2581 if (r_refdef.fog_density)
2583 r_refdef.fogenabled = true;
2584 // this is the point where the fog reaches 0.9986 alpha, which we
2585 // consider a good enough cutoff point for the texture
2586 // (0.9986 * 256 == 255.6)
2587 r_refdef.fogrange = 400 / r_refdef.fog_density;
2588 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2589 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2590 // fog color was already set
2593 r_refdef.fogenabled = false;
2601 void R_RenderView(void)
2603 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2604 return; //Host_Error ("R_RenderView: NULL worldmodel");
2606 R_Shadow_UpdateWorldLightSelection();
2609 if (r_timereport_active)
2610 R_TimeReport("setup");
2613 if (r_timereport_active)
2614 R_TimeReport("visibility");
2616 R_ResetViewRendering3D();
2619 if (r_timereport_active)
2620 R_TimeReport("clear");
2622 R_Bloom_StartFrame();
2624 // this produces a bloom texture to be used in R_BlendView() later
2626 R_HDR_RenderBloomTexture();
2628 r_view.colorscale = r_hdr_scenebrightness.value;
2632 if (r_timereport_active)
2633 R_TimeReport("blendview");
2635 GL_Scissor(0, 0, vid.width, vid.height);
2636 GL_ScissorTest(false);
2640 extern void R_DrawLightningBeams (void);
2641 extern void VM_CL_AddPolygonsToMeshQueue (void);
2642 extern void R_DrawPortals (void);
2643 extern cvar_t cl_locs_show;
2644 static void R_DrawLocs(void);
2645 static void R_DrawEntityBBoxes(void);
2646 void R_RenderScene(void)
2648 // don't let sound skip if going slow
2649 if (r_refdef.extraupdate)
2652 R_ResetViewRendering3D();
2654 R_MeshQueue_BeginScene();
2658 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);
2660 if (cl.csqc_vidvars.drawworld)
2662 // don't let sound skip if going slow
2663 if (r_refdef.extraupdate)
2666 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2668 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2669 if (r_timereport_active)
2670 R_TimeReport("worldsky");
2673 if (R_DrawBrushModelsSky() && r_timereport_active)
2674 R_TimeReport("bmodelsky");
2677 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2679 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2680 if (r_timereport_active)
2681 R_TimeReport("worlddepth");
2683 if (r_depthfirst.integer >= 2)
2685 R_DrawModelsDepth();
2686 if (r_timereport_active)
2687 R_TimeReport("modeldepth");
2690 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2692 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2693 if (r_timereport_active)
2694 R_TimeReport("world");
2697 // don't let sound skip if going slow
2698 if (r_refdef.extraupdate)
2702 if (r_timereport_active)
2703 R_TimeReport("models");
2705 // don't let sound skip if going slow
2706 if (r_refdef.extraupdate)
2709 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2711 R_DrawModelShadows();
2713 R_ResetViewRendering3D();
2715 // don't let sound skip if going slow
2716 if (r_refdef.extraupdate)
2720 R_ShadowVolumeLighting(false);
2721 if (r_timereport_active)
2722 R_TimeReport("rtlights");
2724 // don't let sound skip if going slow
2725 if (r_refdef.extraupdate)
2728 if (cl.csqc_vidvars.drawworld)
2730 R_DrawLightningBeams();
2731 if (r_timereport_active)
2732 R_TimeReport("lightning");
2735 if (r_timereport_active)
2736 R_TimeReport("particles");
2739 if (r_timereport_active)
2740 R_TimeReport("explosions");
2743 if (gl_support_fragment_shader)
2745 qglUseProgramObjectARB(0);CHECKGLERROR
2747 VM_CL_AddPolygonsToMeshQueue();
2749 if (cl_locs_show.integer)
2752 if (r_timereport_active)
2753 R_TimeReport("showlocs");
2756 if (r_drawportals.integer)
2759 if (r_timereport_active)
2760 R_TimeReport("portals");
2763 if (r_showbboxes.value > 0)
2765 R_DrawEntityBBoxes();
2766 if (r_timereport_active)
2767 R_TimeReport("bboxes");
2770 if (gl_support_fragment_shader)
2772 qglUseProgramObjectARB(0);CHECKGLERROR
2774 R_MeshQueue_RenderTransparent();
2775 if (r_timereport_active)
2776 R_TimeReport("drawtrans");
2778 if (gl_support_fragment_shader)
2780 qglUseProgramObjectARB(0);CHECKGLERROR
2783 if (cl.csqc_vidvars.drawworld)
2786 if (r_timereport_active)
2787 R_TimeReport("coronas");
2790 // don't let sound skip if going slow
2791 if (r_refdef.extraupdate)
2794 R_ResetViewRendering2D();
2797 static const int bboxelements[36] =
2807 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2810 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2812 GL_DepthMask(false);
2813 GL_DepthRange(0, 1);
2814 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2815 R_Mesh_Matrix(&identitymatrix);
2816 R_Mesh_ResetTextureState();
2818 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2819 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2820 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2821 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2822 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2823 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2824 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2825 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2826 R_FillColors(color4f, 8, cr, cg, cb, ca);
2827 if (r_refdef.fogenabled)
2829 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2831 f1 = FogPoint_World(v);
2833 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2834 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2835 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2838 R_Mesh_VertexPointer(vertex3f, 0, 0);
2839 R_Mesh_ColorPointer(color4f, 0, 0);
2840 R_Mesh_ResetTextureState();
2841 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2844 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2848 prvm_edict_t *edict;
2849 // this function draws bounding boxes of server entities
2853 for (i = 0;i < numsurfaces;i++)
2855 edict = PRVM_EDICT_NUM(surfacelist[i]);
2856 switch ((int)edict->fields.server->solid)
2858 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2859 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2860 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2861 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2862 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2863 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2865 color[3] *= r_showbboxes.value;
2866 color[3] = bound(0, color[3], 1);
2867 GL_DepthTest(!r_showdisabledepthtest.integer);
2868 GL_CullFace(GL_BACK);
2869 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2874 static void R_DrawEntityBBoxes(void)
2877 prvm_edict_t *edict;
2879 // this function draws bounding boxes of server entities
2883 for (i = 0;i < prog->num_edicts;i++)
2885 edict = PRVM_EDICT_NUM(i);
2886 if (edict->priv.server->free)
2888 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2889 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2894 int nomodelelements[24] =
2906 float nomodelvertex3f[6*3] =
2916 float nomodelcolor4f[6*4] =
2918 0.0f, 0.0f, 0.5f, 1.0f,
2919 0.0f, 0.0f, 0.5f, 1.0f,
2920 0.0f, 0.5f, 0.0f, 1.0f,
2921 0.0f, 0.5f, 0.0f, 1.0f,
2922 0.5f, 0.0f, 0.0f, 1.0f,
2923 0.5f, 0.0f, 0.0f, 1.0f
2926 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2931 // this is only called once per entity so numsurfaces is always 1, and
2932 // surfacelist is always {0}, so this code does not handle batches
2933 R_Mesh_Matrix(&ent->matrix);
2935 if (ent->flags & EF_ADDITIVE)
2937 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2938 GL_DepthMask(false);
2940 else if (ent->alpha < 1)
2942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2943 GL_DepthMask(false);
2947 GL_BlendFunc(GL_ONE, GL_ZERO);
2950 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2951 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2952 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2953 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2954 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2955 if (r_refdef.fogenabled)
2958 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2959 R_Mesh_ColorPointer(color4f, 0, 0);
2960 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2961 f1 = FogPoint_World(org);
2963 for (i = 0, c = color4f;i < 6;i++, c += 4)
2965 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2966 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2967 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2971 else if (ent->alpha != 1)
2973 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2974 R_Mesh_ColorPointer(color4f, 0, 0);
2975 for (i = 0, c = color4f;i < 6;i++, c += 4)
2979 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2980 R_Mesh_ResetTextureState();
2981 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2984 void R_DrawNoModel(entity_render_t *ent)
2987 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2988 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2989 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2991 // R_DrawNoModelCallback(ent, 0);
2994 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2996 vec3_t right1, right2, diff, normal;
2998 VectorSubtract (org2, org1, normal);
3000 // calculate 'right' vector for start
3001 VectorSubtract (r_view.origin, org1, diff);
3002 CrossProduct (normal, diff, right1);
3003 VectorNormalize (right1);
3005 // calculate 'right' vector for end
3006 VectorSubtract (r_view.origin, org2, diff);
3007 CrossProduct (normal, diff, right2);
3008 VectorNormalize (right2);
3010 vert[ 0] = org1[0] + width * right1[0];
3011 vert[ 1] = org1[1] + width * right1[1];
3012 vert[ 2] = org1[2] + width * right1[2];
3013 vert[ 3] = org1[0] - width * right1[0];
3014 vert[ 4] = org1[1] - width * right1[1];
3015 vert[ 5] = org1[2] - width * right1[2];
3016 vert[ 6] = org2[0] - width * right2[0];
3017 vert[ 7] = org2[1] - width * right2[1];
3018 vert[ 8] = org2[2] - width * right2[2];
3019 vert[ 9] = org2[0] + width * right2[0];
3020 vert[10] = org2[1] + width * right2[1];
3021 vert[11] = org2[2] + width * right2[2];
3024 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3026 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)
3031 if (r_refdef.fogenabled)
3032 fog = FogPoint_World(origin);
3034 R_Mesh_Matrix(&identitymatrix);
3035 GL_BlendFunc(blendfunc1, blendfunc2);
3041 GL_CullFace(GL_BACK);
3044 GL_CullFace(GL_FRONT);
3046 GL_DepthMask(false);
3047 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3048 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3049 GL_DepthTest(!depthdisable);
3051 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3052 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3053 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3054 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3055 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3056 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3057 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3058 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3059 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3060 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3061 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3062 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3064 R_Mesh_VertexPointer(vertex3f, 0, 0);
3065 R_Mesh_ColorPointer(NULL, 0, 0);
3066 R_Mesh_ResetTextureState();
3067 R_Mesh_TexBind(0, R_GetTexture(texture));
3068 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3069 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3070 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3071 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3073 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3075 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3076 GL_BlendFunc(blendfunc1, GL_ONE);
3078 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);
3079 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3083 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3088 VectorSet(v, x, y, z);
3089 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3090 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3092 if (i == mesh->numvertices)
3094 if (mesh->numvertices < mesh->maxvertices)
3096 VectorCopy(v, vertex3f);
3097 mesh->numvertices++;
3099 return mesh->numvertices;
3105 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3109 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3110 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3111 e = mesh->element3i + mesh->numtriangles * 3;
3112 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3114 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3115 if (mesh->numtriangles < mesh->maxtriangles)
3120 mesh->numtriangles++;
3122 element[1] = element[2];
3126 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3130 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3131 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3132 e = mesh->element3i + mesh->numtriangles * 3;
3133 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3135 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3136 if (mesh->numtriangles < mesh->maxtriangles)
3141 mesh->numtriangles++;
3143 element[1] = element[2];
3147 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3148 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3150 int planenum, planenum2;
3153 mplane_t *plane, *plane2;
3155 double temppoints[2][256*3];
3156 // figure out how large a bounding box we need to properly compute this brush
3158 for (w = 0;w < numplanes;w++)
3159 maxdist = max(maxdist, planes[w].dist);
3160 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3161 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3162 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3166 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3167 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3169 if (planenum2 == planenum)
3171 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);
3174 if (tempnumpoints < 3)
3176 // generate elements forming a triangle fan for this polygon
3177 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3181 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3184 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3185 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3186 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);
3187 GL_LockArrays(0, brush->numpoints);
3188 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3189 GL_LockArrays(0, 0);
3192 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3195 if (!surface->num_collisiontriangles)
3197 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3198 i = (int)(((size_t)surface) / sizeof(msurface_t));
3199 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);
3200 GL_LockArrays(0, surface->num_collisionvertices);
3201 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3202 GL_LockArrays(0, 0);
3205 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)
3207 texturelayer_t *layer;
3208 layer = t->currentlayers + t->currentnumlayers++;
3210 layer->depthmask = depthmask;
3211 layer->blendfunc1 = blendfunc1;
3212 layer->blendfunc2 = blendfunc2;
3213 layer->texture = texture;
3214 layer->texmatrix = *matrix;
3215 layer->color[0] = r * r_view.colorscale;
3216 layer->color[1] = g * r_view.colorscale;
3217 layer->color[2] = b * r_view.colorscale;
3218 layer->color[3] = a;
3221 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3224 index = parms[2] + r_refdef.time * parms[3];
3225 index -= floor(index);
3229 case Q3WAVEFUNC_NONE:
3230 case Q3WAVEFUNC_NOISE:
3231 case Q3WAVEFUNC_COUNT:
3234 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3235 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3236 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3237 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3238 case Q3WAVEFUNC_TRIANGLE:
3240 f = index - floor(index);
3251 return (float)(parms[0] + parms[1] * f);
3254 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3257 model_t *model = ent->model;
3260 q3shaderinfo_layer_tcmod_t *tcmod;
3262 // switch to an alternate material if this is a q1bsp animated material
3264 texture_t *texture = t;
3265 int s = ent->skinnum;
3266 if ((unsigned int)s >= (unsigned int)model->numskins)
3268 if (model->skinscenes)
3270 if (model->skinscenes[s].framecount > 1)
3271 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3273 s = model->skinscenes[s].firstframe;
3276 t = t + s * model->num_surfaces;
3279 // use an alternate animation if the entity's frame is not 0,
3280 // and only if the texture has an alternate animation
3281 if (ent->frame2 != 0 && t->anim_total[1])
3282 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3284 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3286 texture->currentframe = t;
3289 // update currentskinframe to be a qw skin or animation frame
3290 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3292 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3294 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3295 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3296 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);
3298 t->currentskinframe = r_qwskincache_skinframe[i];
3299 if (t->currentskinframe == NULL)
3300 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3302 else if (t->numskinframes >= 2)
3303 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3304 if (t->backgroundnumskinframes >= 2)
3305 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3307 t->currentmaterialflags = t->basematerialflags;
3308 t->currentalpha = ent->alpha;
3309 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3310 t->currentalpha *= r_wateralpha.value;
3311 if (!(ent->flags & RENDER_LIGHT))
3312 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3313 if (ent->effects & EF_ADDITIVE)
3314 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3315 else if (t->currentalpha < 1)
3316 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3317 if (ent->effects & EF_DOUBLESIDED)
3318 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3319 if (ent->effects & EF_NODEPTHTEST)
3320 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3321 if (ent->flags & RENDER_VIEWMODEL)
3322 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3323 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3324 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3326 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3329 switch(tcmod->tcmod)
3333 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3334 matrix = r_waterscrollmatrix;
3336 matrix = identitymatrix;
3338 case Q3TCMOD_ENTITYTRANSLATE:
3339 // this is used in Q3 to allow the gamecode to control texcoord
3340 // scrolling on the entity, which is not supported in darkplaces yet.
3341 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3343 case Q3TCMOD_ROTATE:
3344 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3345 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3346 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3349 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3351 case Q3TCMOD_SCROLL:
3352 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3354 case Q3TCMOD_STRETCH:
3355 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3356 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3358 case Q3TCMOD_TRANSFORM:
3359 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3360 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3361 VectorSet(tcmat + 6, 0 , 0 , 1);
3362 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3363 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3365 case Q3TCMOD_TURBULENT:
3366 // this is handled in the RSurf_PrepareVertices function
3367 matrix = identitymatrix;
3370 // either replace or concatenate the transformation
3372 t->currenttexmatrix = matrix;
3375 matrix4x4_t temp = t->currenttexmatrix;
3376 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3380 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3381 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3382 t->glosstexture = r_texture_white;
3383 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3384 t->backgroundglosstexture = r_texture_white;
3385 t->specularpower = r_shadow_glossexponent.value;
3386 // TODO: store reference values for these in the texture?
3387 t->specularscale = 0;
3388 if (r_shadow_gloss.integer > 0)
3390 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3392 if (r_shadow_glossintensity.value > 0)
3394 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3395 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3396 t->specularscale = r_shadow_glossintensity.value;
3399 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3400 t->specularscale = r_shadow_gloss2intensity.value;
3403 t->currentpolygonfactor = r_refdef.polygonfactor;
3404 t->currentpolygonoffset = r_refdef.polygonoffset;
3405 // submodels are biased to avoid z-fighting with world surfaces that they
3406 // may be exactly overlapping (avoids z-fighting artifacts on certain
3407 // doors and things in Quake maps)
3408 if (ent->model->brush.submodel)
3410 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3411 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3414 VectorClear(t->dlightcolor);
3415 t->currentnumlayers = 0;
3416 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3418 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3420 int blendfunc1, blendfunc2, depthmask;
3421 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3423 blendfunc1 = GL_SRC_ALPHA;
3424 blendfunc2 = GL_ONE;
3426 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3428 blendfunc1 = GL_SRC_ALPHA;
3429 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3431 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3433 blendfunc1 = t->customblendfunc[0];
3434 blendfunc2 = t->customblendfunc[1];
3438 blendfunc1 = GL_ONE;
3439 blendfunc2 = GL_ZERO;
3441 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3442 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3444 rtexture_t *currentbasetexture;
3446 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3447 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3448 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3449 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3451 // fullbright is not affected by r_refdef.lightmapintensity
3452 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3453 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3454 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);
3455 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3456 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);
3461 // set the color tint used for lights affecting this surface
3462 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3464 // q3bsp has no lightmap updates, so the lightstylevalue that
3465 // would normally be baked into the lightmap must be
3466 // applied to the color
3467 if (ent->model->type == mod_brushq3)
3468 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3469 colorscale *= r_refdef.lightmapintensity;
3470 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);
3471 if (r_ambient.value >= (1.0f/64.0f))
3472 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);
3473 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3475 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);
3476 if (r_ambient.value >= (1.0f/64.0f))
3477 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);
3479 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3481 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);
3482 if (r_ambient.value >= (1.0f/64.0f))
3483 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);
3486 if (t->currentskinframe->glow != NULL)
3487 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);
3488 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3490 // if this is opaque use alpha blend which will darken the earlier
3493 // if this is an alpha blended material, all the earlier passes
3494 // were darkened by fog already, so we only need to add the fog
3495 // color ontop through the fog mask texture
3497 // if this is an additive blended material, all the earlier passes
3498 // were darkened by fog already, and we should not add fog color
3499 // (because the background was not darkened, there is no fog color
3500 // that was lost behind it).
3501 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);
3508 void R_UpdateAllTextureInfo(entity_render_t *ent)
3512 for (i = 0;i < ent->model->num_texturesperskin;i++)
3513 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3516 rsurfacestate_t rsurface;
3518 void R_Mesh_ResizeArrays(int newvertices)
3521 if (rsurface.array_size >= newvertices)
3523 if (rsurface.array_modelvertex3f)
3524 Mem_Free(rsurface.array_modelvertex3f);
3525 rsurface.array_size = (newvertices + 1023) & ~1023;
3526 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3527 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3528 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3529 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3530 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3531 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3532 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3533 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3534 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3535 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3536 rsurface.array_color4f = base + rsurface.array_size * 27;
3537 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3540 void RSurf_CleanUp(void)
3543 if (rsurface.mode == RSURFMODE_GLSL)
3545 qglUseProgramObjectARB(0);CHECKGLERROR
3547 GL_AlphaTest(false);
3548 rsurface.mode = RSURFMODE_NONE;
3549 rsurface.uselightmaptexture = false;
3550 rsurface.texture = NULL;
3553 void RSurf_ActiveWorldEntity(void)
3555 model_t *model = r_refdef.worldmodel;
3557 if (rsurface.array_size < model->surfmesh.num_vertices)
3558 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3559 rsurface.matrix = identitymatrix;
3560 rsurface.inversematrix = identitymatrix;
3561 R_Mesh_Matrix(&identitymatrix);
3562 VectorCopy(r_view.origin, rsurface.modelorg);
3563 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3564 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3565 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3566 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3567 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3568 rsurface.frameblend[0].frame = 0;
3569 rsurface.frameblend[0].lerp = 1;
3570 rsurface.frameblend[1].frame = 0;
3571 rsurface.frameblend[1].lerp = 0;
3572 rsurface.frameblend[2].frame = 0;
3573 rsurface.frameblend[2].lerp = 0;
3574 rsurface.frameblend[3].frame = 0;
3575 rsurface.frameblend[3].lerp = 0;
3576 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3577 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3578 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3579 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3580 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3581 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3582 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3583 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3584 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3585 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3586 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3587 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3588 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3589 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3590 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3591 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3592 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3593 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3594 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3595 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3596 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3597 rsurface.modelelement3i = model->surfmesh.data_element3i;
3598 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3599 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3600 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3601 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3602 rsurface.modelsurfaces = model->data_surfaces;
3603 rsurface.generatedvertex = false;
3604 rsurface.vertex3f = rsurface.modelvertex3f;
3605 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3606 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3607 rsurface.svector3f = rsurface.modelsvector3f;
3608 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3609 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3610 rsurface.tvector3f = rsurface.modeltvector3f;
3611 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3612 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3613 rsurface.normal3f = rsurface.modelnormal3f;
3614 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3615 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3616 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3619 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3621 model_t *model = ent->model;
3623 if (rsurface.array_size < model->surfmesh.num_vertices)
3624 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3625 rsurface.matrix = ent->matrix;
3626 rsurface.inversematrix = ent->inversematrix;
3627 R_Mesh_Matrix(&rsurface.matrix);
3628 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3629 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3630 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3631 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3632 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3633 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3634 rsurface.frameblend[0] = ent->frameblend[0];
3635 rsurface.frameblend[1] = ent->frameblend[1];
3636 rsurface.frameblend[2] = ent->frameblend[2];
3637 rsurface.frameblend[3] = ent->frameblend[3];
3638 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3642 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3643 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3644 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3645 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3646 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3648 else if (wantnormals)
3650 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3651 rsurface.modelsvector3f = NULL;
3652 rsurface.modeltvector3f = NULL;
3653 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3654 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3658 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3659 rsurface.modelsvector3f = NULL;
3660 rsurface.modeltvector3f = NULL;
3661 rsurface.modelnormal3f = NULL;
3662 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3664 rsurface.modelvertex3f_bufferobject = 0;
3665 rsurface.modelvertex3f_bufferoffset = 0;
3666 rsurface.modelsvector3f_bufferobject = 0;
3667 rsurface.modelsvector3f_bufferoffset = 0;
3668 rsurface.modeltvector3f_bufferobject = 0;
3669 rsurface.modeltvector3f_bufferoffset = 0;
3670 rsurface.modelnormal3f_bufferobject = 0;
3671 rsurface.modelnormal3f_bufferoffset = 0;
3672 rsurface.generatedvertex = true;
3676 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3677 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3678 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3679 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3680 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3681 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3682 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3683 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3684 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3685 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3686 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3687 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3688 rsurface.generatedvertex = false;
3690 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3691 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3692 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3693 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3694 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3695 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3696 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3697 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3698 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3699 rsurface.modelelement3i = model->surfmesh.data_element3i;
3700 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3701 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3702 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3703 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3704 rsurface.modelsurfaces = model->data_surfaces;
3705 rsurface.vertex3f = rsurface.modelvertex3f;
3706 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3707 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3708 rsurface.svector3f = rsurface.modelsvector3f;
3709 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3710 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3711 rsurface.tvector3f = rsurface.modeltvector3f;
3712 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3713 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3714 rsurface.normal3f = rsurface.modelnormal3f;
3715 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3716 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3717 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3720 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3721 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3724 int texturesurfaceindex;
3729 const float *v1, *in_tc;
3731 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3733 q3shaderinfo_deform_t *deform;
3734 // 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
3735 if (rsurface.generatedvertex)
3737 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3738 generatenormals = true;
3739 for (i = 0;i < Q3MAXDEFORMS;i++)
3741 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3743 generatetangents = true;
3744 generatenormals = true;
3746 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3747 generatenormals = true;
3749 if (generatenormals && !rsurface.modelnormal3f)
3751 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3752 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3753 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3754 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3756 if (generatetangents && !rsurface.modelsvector3f)
3758 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3759 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3760 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3761 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3762 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3763 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3764 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);
3767 rsurface.vertex3f = rsurface.modelvertex3f;
3768 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3769 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3770 rsurface.svector3f = rsurface.modelsvector3f;
3771 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3772 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3773 rsurface.tvector3f = rsurface.modeltvector3f;
3774 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3775 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3776 rsurface.normal3f = rsurface.modelnormal3f;
3777 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3778 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3779 // if vertices are deformed (sprite flares and things in maps, possibly
3780 // water waves, bulges and other deformations), generate them into
3781 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3782 // (may be static model data or generated data for an animated model, or
3783 // the previous deform pass)
3784 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3786 switch (deform->deform)
3789 case Q3DEFORM_PROJECTIONSHADOW:
3790 case Q3DEFORM_TEXT0:
3791 case Q3DEFORM_TEXT1:
3792 case Q3DEFORM_TEXT2:
3793 case Q3DEFORM_TEXT3:
3794 case Q3DEFORM_TEXT4:
3795 case Q3DEFORM_TEXT5:
3796 case Q3DEFORM_TEXT6:
3797 case Q3DEFORM_TEXT7:
3800 case Q3DEFORM_AUTOSPRITE:
3801 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3802 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3803 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3804 VectorNormalize(newforward);
3805 VectorNormalize(newright);
3806 VectorNormalize(newup);
3807 // make deformed versions of only the model vertices used by the specified surfaces
3808 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3810 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3811 // a single autosprite surface can contain multiple sprites...
3812 for (j = 0;j < surface->num_vertices - 3;j += 4)
3814 VectorClear(center);
3815 for (i = 0;i < 4;i++)
3816 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3817 VectorScale(center, 0.25f, center);
3818 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3819 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3820 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3821 for (i = 0;i < 4;i++)
3823 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3824 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3827 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);
3828 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);
3830 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3831 rsurface.vertex3f_bufferobject = 0;
3832 rsurface.vertex3f_bufferoffset = 0;
3833 rsurface.svector3f = rsurface.array_deformedsvector3f;
3834 rsurface.svector3f_bufferobject = 0;
3835 rsurface.svector3f_bufferoffset = 0;
3836 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3837 rsurface.tvector3f_bufferobject = 0;
3838 rsurface.tvector3f_bufferoffset = 0;
3839 rsurface.normal3f = rsurface.array_deformednormal3f;
3840 rsurface.normal3f_bufferobject = 0;
3841 rsurface.normal3f_bufferoffset = 0;
3843 case Q3DEFORM_AUTOSPRITE2:
3844 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3845 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3846 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3847 VectorNormalize(newforward);
3848 VectorNormalize(newright);
3849 VectorNormalize(newup);
3850 // make deformed versions of only the model vertices used by the specified surfaces
3851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3853 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3854 const float *v1, *v2;
3864 memset(shortest, 0, sizeof(shortest));
3865 // a single autosprite surface can contain multiple sprites...
3866 for (j = 0;j < surface->num_vertices - 3;j += 4)
3868 VectorClear(center);
3869 for (i = 0;i < 4;i++)
3870 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3871 VectorScale(center, 0.25f, center);
3872 // find the two shortest edges, then use them to define the
3873 // axis vectors for rotating around the central axis
3874 for (i = 0;i < 6;i++)
3876 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3877 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3879 Debug_PolygonBegin(NULL, 0, false, 0);
3880 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
3881 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
3882 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
3885 l = VectorDistance2(v1, v2);
3886 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
3888 l += (1.0f / 1024.0f);
3889 if (shortest[0].length2 > l || i == 0)
3891 shortest[1] = shortest[0];
3892 shortest[0].length2 = l;
3893 shortest[0].v1 = v1;
3894 shortest[0].v2 = v2;
3896 else if (shortest[1].length2 > l || i == 1)
3898 shortest[1].length2 = l;
3899 shortest[1].v1 = v1;
3900 shortest[1].v2 = v2;
3903 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
3904 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
3906 Debug_PolygonBegin(NULL, 0, false, 0);
3907 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
3908 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
3909 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
3912 // this calculates the right vector from the shortest edge
3913 // and the up vector from the edge midpoints
3914 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
3915 VectorNormalize(right);
3916 VectorSubtract(end, start, up);
3917 VectorNormalize(up);
3918 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3919 //VectorSubtract(rsurface.modelorg, center, forward);
3920 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
3921 VectorNegate(forward, forward);
3922 VectorReflect(forward, 0, up, forward);
3923 VectorNormalize(forward);
3924 CrossProduct(up, forward, newright);
3925 VectorNormalize(newright);
3927 Debug_PolygonBegin(NULL, 0, false, 0);
3928 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
3929 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
3930 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3934 Debug_PolygonBegin(NULL, 0, false, 0);
3935 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
3936 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
3937 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3940 // rotate the quad around the up axis vector, this is made
3941 // especially easy by the fact we know the quad is flat,
3942 // so we only have to subtract the center position and
3943 // measure distance along the right vector, and then
3944 // multiply that by the newright vector and add back the
3946 // we also need to subtract the old position to undo the
3947 // displacement from the center, which we do with a
3948 // DotProduct, the subtraction/addition of center is also
3949 // optimized into DotProducts here
3950 l = DotProduct(right, center);
3951 for (i = 0;i < 4;i++)
3953 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3954 f = DotProduct(right, v1) - l;
3955 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3958 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);
3959 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);
3961 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3962 rsurface.vertex3f_bufferobject = 0;
3963 rsurface.vertex3f_bufferoffset = 0;
3964 rsurface.svector3f = rsurface.array_deformedsvector3f;
3965 rsurface.svector3f_bufferobject = 0;
3966 rsurface.svector3f_bufferoffset = 0;
3967 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3968 rsurface.tvector3f_bufferobject = 0;
3969 rsurface.tvector3f_bufferoffset = 0;
3970 rsurface.normal3f = rsurface.array_deformednormal3f;
3971 rsurface.normal3f_bufferobject = 0;
3972 rsurface.normal3f_bufferoffset = 0;
3974 case Q3DEFORM_NORMAL:
3975 // deform the normals to make reflections wavey
3976 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3978 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3979 for (j = 0;j < surface->num_vertices;j++)
3982 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
3983 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
3984 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
3985 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3986 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3987 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3988 VectorNormalize(normal);
3990 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);
3992 rsurface.svector3f = rsurface.array_deformedsvector3f;
3993 rsurface.svector3f_bufferobject = 0;
3994 rsurface.svector3f_bufferoffset = 0;
3995 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3996 rsurface.tvector3f_bufferobject = 0;
3997 rsurface.tvector3f_bufferoffset = 0;
3998 rsurface.normal3f = rsurface.array_deformednormal3f;
3999 rsurface.normal3f_bufferobject = 0;
4000 rsurface.normal3f_bufferoffset = 0;
4003 // deform vertex array to make wavey water and flags and such
4004 waveparms[0] = deform->waveparms[0];
4005 waveparms[1] = deform->waveparms[1];
4006 waveparms[2] = deform->waveparms[2];
4007 waveparms[3] = deform->waveparms[3];
4008 // this is how a divisor of vertex influence on deformation
4009 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4010 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4014 for (j = 0;j < surface->num_vertices;j++)
4016 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4017 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4018 // if the wavefunc depends on time, evaluate it per-vertex
4021 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4022 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4024 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4027 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4028 rsurface.vertex3f_bufferobject = 0;
4029 rsurface.vertex3f_bufferoffset = 0;
4031 case Q3DEFORM_BULGE:
4032 // deform vertex array to make the surface have moving bulges
4033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4035 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4036 for (j = 0;j < surface->num_vertices;j++)
4038 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4039 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4042 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4043 rsurface.vertex3f_bufferobject = 0;
4044 rsurface.vertex3f_bufferoffset = 0;
4047 // deform vertex array
4048 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4049 VectorScale(deform->parms, scale, waveparms);
4050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4053 for (j = 0;j < surface->num_vertices;j++)
4054 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4056 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4057 rsurface.vertex3f_bufferobject = 0;
4058 rsurface.vertex3f_bufferoffset = 0;
4062 // generate texcoords based on the chosen texcoord source
4063 switch(rsurface.texture->tcgen.tcgen)
4066 case Q3TCGEN_TEXTURE:
4067 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4068 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4069 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4071 case Q3TCGEN_LIGHTMAP:
4072 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4073 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4074 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4076 case Q3TCGEN_VECTOR:
4077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4079 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4080 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)
4082 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4083 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4086 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4087 rsurface.texcoordtexture2f_bufferobject = 0;
4088 rsurface.texcoordtexture2f_bufferoffset = 0;
4090 case Q3TCGEN_ENVIRONMENT:
4091 // make environment reflections using a spheremap
4092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4094 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4095 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4096 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4097 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4098 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4100 float l, d, eyedir[3];
4101 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4102 l = 0.5f / VectorLength(eyedir);
4103 d = DotProduct(normal, eyedir)*2;
4104 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4105 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4108 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4109 rsurface.texcoordtexture2f_bufferobject = 0;
4110 rsurface.texcoordtexture2f_bufferoffset = 0;
4113 // the only tcmod that needs software vertex processing is turbulent, so
4114 // check for it here and apply the changes if needed
4115 // and we only support that as the first one
4116 // (handling a mixture of turbulent and other tcmods would be problematic
4117 // without punting it entirely to a software path)
4118 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4120 amplitude = rsurface.texture->tcmods[0].parms[1];
4121 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4122 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4124 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4125 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)
4127 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4128 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4131 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4132 rsurface.texcoordtexture2f_bufferobject = 0;
4133 rsurface.texcoordtexture2f_bufferoffset = 0;
4135 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4136 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4137 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4138 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4141 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4144 const msurface_t *surface = texturesurfacelist[0];
4145 const msurface_t *surface2;
4150 // TODO: lock all array ranges before render, rather than on each surface
4151 if (texturenumsurfaces == 1)
4153 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4154 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));
4156 else if (r_batchmode.integer == 2)
4158 #define MAXBATCHTRIANGLES 4096
4159 int batchtriangles = 0;
4160 int batchelements[MAXBATCHTRIANGLES*3];
4161 for (i = 0;i < texturenumsurfaces;i = j)
4163 surface = texturesurfacelist[i];
4165 if (surface->num_triangles > MAXBATCHTRIANGLES)
4167 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));
4170 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4171 batchtriangles = surface->num_triangles;
4172 firstvertex = surface->num_firstvertex;
4173 endvertex = surface->num_firstvertex + surface->num_vertices;
4174 for (;j < texturenumsurfaces;j++)
4176 surface2 = texturesurfacelist[j];
4177 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4179 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4180 batchtriangles += surface2->num_triangles;
4181 firstvertex = min(firstvertex, surface2->num_firstvertex);
4182 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4184 surface2 = texturesurfacelist[j-1];
4185 numvertices = endvertex - firstvertex;
4186 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4189 else if (r_batchmode.integer == 1)
4191 for (i = 0;i < texturenumsurfaces;i = j)
4193 surface = texturesurfacelist[i];
4194 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4195 if (texturesurfacelist[j] != surface2)
4197 surface2 = texturesurfacelist[j-1];
4198 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4199 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4200 GL_LockArrays(surface->num_firstvertex, numvertices);
4201 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4206 for (i = 0;i < texturenumsurfaces;i++)
4208 surface = texturesurfacelist[i];
4209 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4210 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));
4215 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4219 const msurface_t *surface = texturesurfacelist[0];
4220 const msurface_t *surface2;
4225 // TODO: lock all array ranges before render, rather than on each surface
4226 if (texturenumsurfaces == 1)
4228 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4229 if (deluxemaptexunit >= 0)
4230 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4231 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4232 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));
4234 else if (r_batchmode.integer == 2)
4236 #define MAXBATCHTRIANGLES 4096
4237 int batchtriangles = 0;
4238 int batchelements[MAXBATCHTRIANGLES*3];
4239 for (i = 0;i < texturenumsurfaces;i = j)
4241 surface = texturesurfacelist[i];
4242 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4243 if (deluxemaptexunit >= 0)
4244 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4246 if (surface->num_triangles > MAXBATCHTRIANGLES)
4248 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));
4251 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4252 batchtriangles = surface->num_triangles;
4253 firstvertex = surface->num_firstvertex;
4254 endvertex = surface->num_firstvertex + surface->num_vertices;
4255 for (;j < texturenumsurfaces;j++)
4257 surface2 = texturesurfacelist[j];
4258 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4260 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4261 batchtriangles += surface2->num_triangles;
4262 firstvertex = min(firstvertex, surface2->num_firstvertex);
4263 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4265 surface2 = texturesurfacelist[j-1];
4266 numvertices = endvertex - firstvertex;
4267 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4270 else if (r_batchmode.integer == 1)
4273 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4274 for (i = 0;i < texturenumsurfaces;i = j)
4276 surface = texturesurfacelist[i];
4277 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4278 if (texturesurfacelist[j] != surface2)
4280 Con_Printf(" %i", j - i);
4283 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4285 for (i = 0;i < texturenumsurfaces;i = j)
4287 surface = texturesurfacelist[i];
4288 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4289 if (deluxemaptexunit >= 0)
4290 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4291 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4292 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4295 Con_Printf(" %i", j - i);
4297 surface2 = texturesurfacelist[j-1];
4298 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4299 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4300 GL_LockArrays(surface->num_firstvertex, numvertices);
4301 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4309 for (i = 0;i < texturenumsurfaces;i++)
4311 surface = texturesurfacelist[i];
4312 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4313 if (deluxemaptexunit >= 0)
4314 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4315 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4316 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));
4321 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4324 int texturesurfaceindex;
4325 if (r_showsurfaces.integer == 2)
4327 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4329 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4330 for (j = 0;j < surface->num_triangles;j++)
4332 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4333 GL_Color(f, f, f, 1);
4334 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)));
4340 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4342 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4343 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4344 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);
4345 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4346 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));
4351 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4353 int texturesurfaceindex;
4357 if (rsurface.lightmapcolor4f)
4359 // generate color arrays for the surfaces in this list
4360 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4362 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4363 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)
4365 f = FogPoint_Model(v);
4375 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4377 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4378 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)
4380 f = FogPoint_Model(v);
4388 rsurface.lightmapcolor4f = rsurface.array_color4f;
4389 rsurface.lightmapcolor4f_bufferobject = 0;
4390 rsurface.lightmapcolor4f_bufferoffset = 0;
4393 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4395 int texturesurfaceindex;
4398 if (!rsurface.lightmapcolor4f)
4400 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4402 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4403 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)
4411 rsurface.lightmapcolor4f = rsurface.array_color4f;
4412 rsurface.lightmapcolor4f_bufferobject = 0;
4413 rsurface.lightmapcolor4f_bufferoffset = 0;
4416 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4419 rsurface.lightmapcolor4f = NULL;
4420 rsurface.lightmapcolor4f_bufferobject = 0;
4421 rsurface.lightmapcolor4f_bufferoffset = 0;
4422 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4423 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4424 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4425 GL_Color(r, g, b, a);
4426 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4429 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4431 // TODO: optimize applyfog && applycolor case
4432 // just apply fog if necessary, and tint the fog color array if necessary
4433 rsurface.lightmapcolor4f = NULL;
4434 rsurface.lightmapcolor4f_bufferobject = 0;
4435 rsurface.lightmapcolor4f_bufferoffset = 0;
4436 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4437 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4438 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4439 GL_Color(r, g, b, a);
4440 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4443 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4445 int texturesurfaceindex;
4449 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4451 // generate color arrays for the surfaces in this list
4452 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4454 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4455 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4457 if (surface->lightmapinfo->samples)
4459 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4460 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4461 VectorScale(lm, scale, c);
4462 if (surface->lightmapinfo->styles[1] != 255)
4464 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4466 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4467 VectorMA(c, scale, lm, c);
4468 if (surface->lightmapinfo->styles[2] != 255)
4471 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4472 VectorMA(c, scale, lm, c);
4473 if (surface->lightmapinfo->styles[3] != 255)
4476 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4477 VectorMA(c, scale, lm, c);
4487 rsurface.lightmapcolor4f = rsurface.array_color4f;
4488 rsurface.lightmapcolor4f_bufferobject = 0;
4489 rsurface.lightmapcolor4f_bufferoffset = 0;
4493 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4494 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4495 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4497 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4498 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4499 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4500 GL_Color(r, g, b, a);
4501 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4504 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4506 int texturesurfaceindex;
4510 vec3_t ambientcolor;
4511 vec3_t diffusecolor;
4515 VectorCopy(rsurface.modellight_lightdir, lightdir);
4516 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4517 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4518 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4519 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4520 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4521 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4522 if (VectorLength2(diffusecolor) > 0)
4524 // generate color arrays for the surfaces in this list
4525 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4527 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4528 int numverts = surface->num_vertices;
4529 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4530 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4531 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4532 // q3-style directional shading
4533 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4535 if ((f = DotProduct(c2, lightdir)) > 0)
4536 VectorMA(ambientcolor, f, diffusecolor, c);
4538 VectorCopy(ambientcolor, c);
4547 rsurface.lightmapcolor4f = rsurface.array_color4f;
4548 rsurface.lightmapcolor4f_bufferobject = 0;
4549 rsurface.lightmapcolor4f_bufferoffset = 0;
4553 r = ambientcolor[0];
4554 g = ambientcolor[1];
4555 b = ambientcolor[2];
4556 rsurface.lightmapcolor4f = NULL;
4557 rsurface.lightmapcolor4f_bufferobject = 0;
4558 rsurface.lightmapcolor4f_bufferoffset = 0;
4560 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4561 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4562 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4563 GL_Color(r, g, b, a);
4564 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4567 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4569 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4570 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4571 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4572 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4573 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4575 rsurface.mode = RSURFMODE_SHOWSURFACES;
4577 GL_BlendFunc(GL_ONE, GL_ZERO);
4578 R_Mesh_ColorPointer(NULL, 0, 0);
4579 R_Mesh_ResetTextureState();
4581 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4582 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4585 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4587 // transparent sky would be ridiculous
4588 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4590 if (rsurface.mode != RSURFMODE_SKY)
4592 if (rsurface.mode == RSURFMODE_GLSL)
4594 qglUseProgramObjectARB(0);CHECKGLERROR
4596 rsurface.mode = RSURFMODE_SKY;
4600 skyrendernow = false;
4602 // restore entity matrix
4603 R_Mesh_Matrix(&rsurface.matrix);
4605 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4606 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4607 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4608 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4610 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4611 // skymasking on them, and Quake3 never did sky masking (unlike
4612 // software Quake and software Quake2), so disable the sky masking
4613 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4614 // and skymasking also looks very bad when noclipping outside the
4615 // level, so don't use it then either.
4616 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4618 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4619 R_Mesh_ColorPointer(NULL, 0, 0);
4620 R_Mesh_ResetTextureState();
4621 if (skyrendermasked)
4623 // depth-only (masking)
4624 GL_ColorMask(0,0,0,0);
4625 // just to make sure that braindead drivers don't draw
4626 // anything despite that colormask...
4627 GL_BlendFunc(GL_ZERO, GL_ONE);
4632 GL_BlendFunc(GL_ONE, GL_ZERO);
4634 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4635 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4636 if (skyrendermasked)
4637 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4641 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4643 if (rsurface.mode != RSURFMODE_GLSL)
4645 rsurface.mode = RSURFMODE_GLSL;
4646 R_Mesh_ResetTextureState();
4649 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4650 if (!r_glsl_permutation)
4653 if (rsurface.lightmode == 2)
4654 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4656 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4657 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4658 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4659 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4660 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4661 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4663 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]);
4664 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4666 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4667 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4668 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4669 R_Mesh_ColorPointer(NULL, 0, 0);
4671 else if (rsurface.uselightmaptexture)
4673 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4674 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4675 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4676 R_Mesh_ColorPointer(NULL, 0, 0);
4680 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4681 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4682 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4683 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4686 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4687 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4689 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4690 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4695 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4697 // OpenGL 1.3 path - anything not completely ancient
4698 int texturesurfaceindex;
4699 qboolean applycolor;
4703 const texturelayer_t *layer;
4704 if (rsurface.mode != RSURFMODE_MULTIPASS)
4705 rsurface.mode = RSURFMODE_MULTIPASS;
4706 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4707 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4710 int layertexrgbscale;
4711 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4713 if (layerindex == 0)
4717 GL_AlphaTest(false);
4718 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4721 GL_DepthMask(layer->depthmask);
4722 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4723 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4725 layertexrgbscale = 4;
4726 VectorScale(layer->color, 0.25f, layercolor);
4728 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4730 layertexrgbscale = 2;
4731 VectorScale(layer->color, 0.5f, layercolor);
4735 layertexrgbscale = 1;
4736 VectorScale(layer->color, 1.0f, layercolor);
4738 layercolor[3] = layer->color[3];
4739 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4740 R_Mesh_ColorPointer(NULL, 0, 0);
4741 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4742 switch (layer->type)
4744 case TEXTURELAYERTYPE_LITTEXTURE:
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 m.tex[1] = R_GetTexture(layer->texture);
4751 m.texmatrix[1] = layer->texmatrix;
4752 m.texrgbscale[1] = layertexrgbscale;
4753 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4754 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4755 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4756 R_Mesh_TextureState(&m);
4757 if (rsurface.lightmode == 2)
4758 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4759 else if (rsurface.uselightmaptexture)
4760 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4762 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4764 case TEXTURELAYERTYPE_TEXTURE:
4765 memset(&m, 0, sizeof(m));
4766 m.tex[0] = R_GetTexture(layer->texture);
4767 m.texmatrix[0] = layer->texmatrix;
4768 m.texrgbscale[0] = layertexrgbscale;
4769 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4770 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4771 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4772 R_Mesh_TextureState(&m);
4773 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4775 case TEXTURELAYERTYPE_FOG:
4776 memset(&m, 0, sizeof(m));
4777 m.texrgbscale[0] = layertexrgbscale;
4780 m.tex[0] = R_GetTexture(layer->texture);
4781 m.texmatrix[0] = layer->texmatrix;
4782 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4783 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4784 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4786 R_Mesh_TextureState(&m);
4787 // generate a color array for the fog pass
4788 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4789 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4793 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4794 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)
4796 f = 1 - FogPoint_Model(v);
4797 c[0] = layercolor[0];
4798 c[1] = layercolor[1];
4799 c[2] = layercolor[2];
4800 c[3] = f * layercolor[3];
4803 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4806 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4808 GL_LockArrays(0, 0);
4811 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4813 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4814 GL_AlphaTest(false);
4818 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4820 // OpenGL 1.1 - crusty old voodoo path
4821 int texturesurfaceindex;
4825 const texturelayer_t *layer;
4826 if (rsurface.mode != RSURFMODE_MULTIPASS)
4827 rsurface.mode = RSURFMODE_MULTIPASS;
4828 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4829 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4831 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4833 if (layerindex == 0)
4837 GL_AlphaTest(false);
4838 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4841 GL_DepthMask(layer->depthmask);
4842 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4843 R_Mesh_ColorPointer(NULL, 0, 0);
4844 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4845 switch (layer->type)
4847 case TEXTURELAYERTYPE_LITTEXTURE:
4848 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4850 // two-pass lit texture with 2x rgbscale
4851 // first the lightmap pass
4852 memset(&m, 0, sizeof(m));
4853 m.tex[0] = R_GetTexture(r_texture_white);
4854 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4855 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4856 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4857 R_Mesh_TextureState(&m);
4858 if (rsurface.lightmode == 2)
4859 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4860 else if (rsurface.uselightmaptexture)
4861 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4863 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4864 GL_LockArrays(0, 0);
4865 // then apply the texture to it
4866 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4867 memset(&m, 0, sizeof(m));
4868 m.tex[0] = R_GetTexture(layer->texture);
4869 m.texmatrix[0] = layer->texmatrix;
4870 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4871 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4872 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4873 R_Mesh_TextureState(&m);
4874 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);
4878 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4879 memset(&m, 0, sizeof(m));
4880 m.tex[0] = R_GetTexture(layer->texture);
4881 m.texmatrix[0] = layer->texmatrix;
4882 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4883 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4884 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4885 R_Mesh_TextureState(&m);
4886 if (rsurface.lightmode == 2)
4887 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);
4889 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);
4892 case TEXTURELAYERTYPE_TEXTURE:
4893 // singletexture unlit texture with transparency support
4894 memset(&m, 0, sizeof(m));
4895 m.tex[0] = R_GetTexture(layer->texture);
4896 m.texmatrix[0] = layer->texmatrix;
4897 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4898 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4899 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4900 R_Mesh_TextureState(&m);
4901 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);
4903 case TEXTURELAYERTYPE_FOG:
4904 // singletexture fogging
4905 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4908 memset(&m, 0, sizeof(m));
4909 m.tex[0] = R_GetTexture(layer->texture);
4910 m.texmatrix[0] = layer->texmatrix;
4911 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4912 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4913 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4914 R_Mesh_TextureState(&m);
4917 R_Mesh_ResetTextureState();
4918 // generate a color array for the fog pass
4919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4924 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)
4926 f = 1 - FogPoint_Model(v);
4927 c[0] = layer->color[0];
4928 c[1] = layer->color[1];
4929 c[2] = layer->color[2];
4930 c[3] = f * layer->color[3];
4933 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4936 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4938 GL_LockArrays(0, 0);
4941 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4943 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4944 GL_AlphaTest(false);
4948 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4950 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4952 rsurface.rtlight = NULL;
4956 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4958 if (rsurface.mode != RSURFMODE_MULTIPASS)
4959 rsurface.mode = RSURFMODE_MULTIPASS;
4960 if (r_depthfirst.integer == 3)
4962 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4963 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4967 GL_ColorMask(0,0,0,0);
4970 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4971 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4972 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4974 GL_BlendFunc(GL_ONE, GL_ZERO);
4976 GL_AlphaTest(false);
4977 R_Mesh_ColorPointer(NULL, 0, 0);
4978 R_Mesh_ResetTextureState();
4979 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4980 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4981 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4982 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4984 else if (r_depthfirst.integer == 3)
4986 else if (r_showsurfaces.integer)
4988 if (rsurface.mode != RSURFMODE_MULTIPASS)
4989 rsurface.mode = RSURFMODE_MULTIPASS;
4990 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4991 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4993 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4994 GL_BlendFunc(GL_ONE, GL_ZERO);
4995 GL_DepthMask(writedepth);
4997 GL_AlphaTest(false);
4998 R_Mesh_ColorPointer(NULL, 0, 0);
4999 R_Mesh_ResetTextureState();
5000 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5001 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5002 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5004 else if (gl_lightmaps.integer)
5007 if (rsurface.mode != RSURFMODE_MULTIPASS)
5008 rsurface.mode = RSURFMODE_MULTIPASS;
5009 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5011 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5012 GL_BlendFunc(GL_ONE, GL_ZERO);
5013 GL_DepthMask(writedepth);
5015 GL_AlphaTest(false);
5016 R_Mesh_ColorPointer(NULL, 0, 0);
5017 memset(&m, 0, sizeof(m));
5018 m.tex[0] = R_GetTexture(r_texture_white);
5019 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5020 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5021 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5022 R_Mesh_TextureState(&m);
5023 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5024 if (rsurface.lightmode == 2)
5025 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5026 else if (rsurface.uselightmaptexture)
5027 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5029 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5030 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5032 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5034 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5035 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5037 else if (rsurface.texture->currentnumlayers)
5039 // write depth for anything we skipped on the depth-only pass earlier
5040 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5042 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5043 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5044 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5045 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5046 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5047 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5048 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5049 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5050 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5051 if (r_glsl.integer && gl_support_fragment_shader)
5052 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5053 else if (gl_combine.integer && r_textureunits.integer >= 2)
5054 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5056 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5057 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5060 GL_LockArrays(0, 0);
5063 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5066 int texturenumsurfaces, endsurface;
5068 msurface_t *surface;
5069 msurface_t *texturesurfacelist[1024];
5071 // if the model is static it doesn't matter what value we give for
5072 // wantnormals and wanttangents, so this logic uses only rules applicable
5073 // to a model, knowing that they are meaningless otherwise
5074 if (ent == r_refdef.worldentity)
5075 RSurf_ActiveWorldEntity();
5076 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5077 RSurf_ActiveModelEntity(ent, false, false);
5079 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5081 for (i = 0;i < numsurfaces;i = j)
5084 surface = rsurface.modelsurfaces + surfacelist[i];
5085 texture = surface->texture;
5086 R_UpdateTextureInfo(ent, texture);
5087 rsurface.texture = texture->currentframe;
5088 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5089 // scan ahead until we find a different texture
5090 endsurface = min(i + 1024, numsurfaces);
5091 texturenumsurfaces = 0;
5092 texturesurfacelist[texturenumsurfaces++] = surface;
5093 for (;j < endsurface;j++)
5095 surface = rsurface.modelsurfaces + surfacelist[j];
5096 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5098 texturesurfacelist[texturenumsurfaces++] = surface;
5100 // render the range of surfaces
5101 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5107 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5110 vec3_t tempcenter, center;
5112 // break the surface list down into batches by texture and use of lightmapping
5113 for (i = 0;i < numsurfaces;i = j)
5116 // texture is the base texture pointer, rsurface.texture is the
5117 // current frame/skin the texture is directing us to use (for example
5118 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5119 // use skin 1 instead)
5120 texture = surfacelist[i]->texture;
5121 rsurface.texture = texture->currentframe;
5122 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5123 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5125 // if this texture is not the kind we want, skip ahead to the next one
5126 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5130 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5132 // transparent surfaces get pushed off into the transparent queue
5133 const msurface_t *surface = surfacelist[i];
5136 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5137 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5138 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5139 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5140 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5144 // simply scan ahead until we find a different texture or lightmap state
5145 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5147 // render the range of surfaces
5148 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5153 float locboxvertex3f[6*4*3] =
5155 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5156 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5157 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5158 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5159 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5160 1,0,0, 0,0,0, 0,1,0, 1,1,0
5163 int locboxelement3i[6*2*3] =
5173 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5176 cl_locnode_t *loc = (cl_locnode_t *)ent;
5178 float vertex3f[6*4*3];
5180 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5181 GL_DepthMask(false);
5182 GL_DepthRange(0, 1);
5183 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5185 GL_CullFace(GL_NONE);
5186 R_Mesh_Matrix(&identitymatrix);
5188 R_Mesh_VertexPointer(vertex3f, 0, 0);
5189 R_Mesh_ColorPointer(NULL, 0, 0);
5190 R_Mesh_ResetTextureState();
5193 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5194 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5195 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5196 surfacelist[0] < 0 ? 0.5f : 0.125f);
5198 if (VectorCompare(loc->mins, loc->maxs))
5200 VectorSet(size, 2, 2, 2);
5201 VectorMA(loc->mins, -0.5f, size, mins);
5205 VectorCopy(loc->mins, mins);
5206 VectorSubtract(loc->maxs, loc->mins, size);
5209 for (i = 0;i < 6*4*3;)
5210 for (j = 0;j < 3;j++, i++)
5211 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5213 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5216 void R_DrawLocs(void)
5219 cl_locnode_t *loc, *nearestloc;
5221 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5222 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5224 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5225 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5229 void R_DrawCollisionBrushes(entity_render_t *ent)
5233 msurface_t *surface;
5234 model_t *model = ent->model;
5235 if (!model->brush.num_brushes)
5238 R_Mesh_ColorPointer(NULL, 0, 0);
5239 R_Mesh_ResetTextureState();
5240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5241 GL_DepthMask(false);
5242 GL_DepthRange(0, 1);
5243 GL_DepthTest(!r_showdisabledepthtest.integer);
5244 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5245 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5246 if (brush->colbrushf && brush->colbrushf->numtriangles)
5247 R_DrawCollisionBrush(brush->colbrushf);
5248 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5249 if (surface->num_collisiontriangles)
5250 R_DrawCollisionSurface(ent, surface);
5251 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5254 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5257 const int *elements;
5258 msurface_t *surface;
5259 model_t *model = ent->model;
5262 GL_DepthRange(0, 1);
5263 GL_DepthTest(!r_showdisabledepthtest.integer);
5264 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5266 GL_BlendFunc(GL_ONE, GL_ZERO);
5267 R_Mesh_ColorPointer(NULL, 0, 0);
5268 R_Mesh_ResetTextureState();
5269 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5271 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5273 rsurface.texture = surface->texture->currentframe;
5274 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5276 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5279 if (!rsurface.texture->currentlayers->depthmask)
5280 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5281 else if (ent == r_refdef.worldentity)
5282 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5284 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5285 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5288 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5290 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5291 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5292 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5293 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5300 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5302 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5304 VectorCopy(rsurface.vertex3f + l * 3, v);
5305 qglVertex3f(v[0], v[1], v[2]);
5306 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5307 qglVertex3f(v[0], v[1], v[2]);
5311 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5313 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5315 VectorCopy(rsurface.vertex3f + l * 3, v);
5316 qglVertex3f(v[0], v[1], v[2]);
5317 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5318 qglVertex3f(v[0], v[1], v[2]);
5322 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5324 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5326 VectorCopy(rsurface.vertex3f + l * 3, v);
5327 qglVertex3f(v[0], v[1], v[2]);
5328 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5329 qglVertex3f(v[0], v[1], v[2]);
5336 rsurface.texture = NULL;
5339 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5340 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5342 int i, j, endj, f, flagsmask;
5343 int counttriangles = 0;
5344 msurface_t *surface, **surfacechain;
5346 model_t *model = r_refdef.worldmodel;
5347 const int maxsurfacelist = 1024;
5348 int numsurfacelist = 0;
5349 msurface_t *surfacelist[1024];
5353 RSurf_ActiveWorldEntity();
5355 // update light styles
5356 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5358 for (i = 0;i < model->brushq1.light_styles;i++)
5360 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5362 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5363 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5364 for (;(surface = *surfacechain);surfacechain++)
5365 surface->cached_dlight = true;
5370 R_UpdateAllTextureInfo(r_refdef.worldentity);
5371 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5374 rsurface.uselightmaptexture = false;
5375 rsurface.texture = NULL;
5377 j = model->firstmodelsurface;
5378 endj = j + model->nummodelsurfaces;
5381 // quickly skip over non-visible surfaces
5382 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5384 // quickly iterate over visible surfaces
5385 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5387 // process this surface
5388 surface = model->data_surfaces + j;
5389 // if this surface fits the criteria, add it to the list
5390 if (surface->num_triangles)
5392 // if lightmap parameters changed, rebuild lightmap texture
5393 if (surface->cached_dlight)
5394 R_BuildLightMap(r_refdef.worldentity, surface);
5395 // add face to draw list
5396 surfacelist[numsurfacelist++] = surface;
5397 counttriangles += surface->num_triangles;
5398 if (numsurfacelist >= maxsurfacelist)
5400 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5407 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5408 r_refdef.stats.entities_triangles += counttriangles;
5411 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5412 R_DrawCollisionBrushes(r_refdef.worldentity);
5414 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5415 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5418 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5420 int i, f, flagsmask;
5421 int counttriangles = 0;
5422 msurface_t *surface, *endsurface, **surfacechain;
5424 model_t *model = ent->model;
5425 const int maxsurfacelist = 1024;
5426 int numsurfacelist = 0;
5427 msurface_t *surfacelist[1024];
5431 // if the model is static it doesn't matter what value we give for
5432 // wantnormals and wanttangents, so this logic uses only rules applicable
5433 // to a model, knowing that they are meaningless otherwise
5434 if (ent == r_refdef.worldentity)
5435 RSurf_ActiveWorldEntity();
5436 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5437 RSurf_ActiveModelEntity(ent, false, false);
5439 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5441 // update light styles
5442 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5444 for (i = 0;i < model->brushq1.light_styles;i++)
5446 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5448 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5449 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5450 for (;(surface = *surfacechain);surfacechain++)
5451 surface->cached_dlight = true;
5456 R_UpdateAllTextureInfo(ent);
5457 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5460 rsurface.uselightmaptexture = false;
5461 rsurface.texture = NULL;
5463 surface = model->data_surfaces + model->firstmodelsurface;
5464 endsurface = surface + model->nummodelsurfaces;
5465 for (;surface < endsurface;surface++)
5467 // if this surface fits the criteria, add it to the list
5468 if (surface->num_triangles)
5470 // if lightmap parameters changed, rebuild lightmap texture
5471 if (surface->cached_dlight)
5472 R_BuildLightMap(ent, surface);
5473 // add face to draw list
5474 surfacelist[numsurfacelist++] = surface;
5475 counttriangles += surface->num_triangles;
5476 if (numsurfacelist >= maxsurfacelist)
5478 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5484 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5485 r_refdef.stats.entities_triangles += counttriangles;
5488 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5489 R_DrawCollisionBrushes(ent);
5491 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5492 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);