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 = SceneBrightness / (ContrastBoostCoeff + 1 / color.rgb);\n"
660 //" color.rgb *= SceneBrightness / (ContrastBoostCoeff * color.rgb + 1);\n"
661 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + 1);\n"
662 //" color.rgb *= SceneBrightness; color.rgb /= ContrastBoostCoeff * color.rgb + 1;\n"
664 " color.rgb *= SceneBrightness;\n"
667 " gl_FragColor = vec4(color);\n"
670 "#endif // FRAGMENT_SHADER\n"
673 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
674 const char *permutationinfo[][2] =
676 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
677 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
678 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
679 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
680 {"#define USEGLOW\n", " glow"},
681 {"#define USEFOG\n", " fog"},
682 {"#define USECOLORMAPPING\n", " colormapping"},
683 {"#define USEDIFFUSE\n", " diffuse"},
684 {"#define USECONTRASTBOOST\n", " contrastboost"},
685 {"#define USESPECULAR\n", " specular"},
686 {"#define USECUBEFILTER\n", " cubefilter"},
687 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
688 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
692 void R_GLSL_CompilePermutation(const char *filename, int permutation)
695 qboolean shaderfound;
696 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
697 int vertstrings_count;
698 int geomstrings_count;
699 int fragstrings_count;
701 const char *vertstrings_list[32+1];
702 const char *geomstrings_list[32+1];
703 const char *fragstrings_list[32+1];
704 char permutationname[256];
709 vertstrings_list[0] = "#define VERTEX_SHADER\n";
710 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
711 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
712 vertstrings_count = 1;
713 geomstrings_count = 1;
714 fragstrings_count = 1;
715 permutationname[0] = 0;
716 for (i = 0;permutationinfo[i][0];i++)
718 if (permutation & (1<<i))
720 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
721 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
722 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
723 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
727 // keep line numbers correct
728 vertstrings_list[vertstrings_count++] = "\n";
729 geomstrings_list[geomstrings_count++] = "\n";
730 fragstrings_list[fragstrings_count++] = "\n";
733 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
737 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
738 vertstrings_list[vertstrings_count++] = shaderstring;
739 geomstrings_list[geomstrings_count++] = shaderstring;
740 fragstrings_list[fragstrings_count++] = shaderstring;
743 else if (!strcmp(filename, "glsl/default.glsl"))
745 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
746 vertstrings_list[vertstrings_count++] = builtinshaderstring;
747 geomstrings_list[geomstrings_count++] = builtinshaderstring;
748 fragstrings_list[fragstrings_count++] = builtinshaderstring;
751 // clear any lists that are not needed by this shader
752 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
753 vertstrings_count = 0;
754 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
755 geomstrings_count = 0;
756 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
757 fragstrings_count = 0;
758 // compile the shader program
759 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
760 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
764 qglUseProgramObjectARB(p->program);CHECKGLERROR
765 // look up all the uniform variable names we care about, so we don't
766 // have to look them up every time we set them
767 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
768 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
769 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
770 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
771 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
772 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
773 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
774 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
775 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
776 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
777 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
778 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
779 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
780 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
781 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
782 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
783 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
784 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
785 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
786 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
787 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
788 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
789 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
790 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
791 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
792 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
793 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
794 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
795 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
796 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
797 // initialize the samplers to refer to the texture units we use
798 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
799 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
800 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
801 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
802 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
803 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
804 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
805 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
806 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
807 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
808 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
810 qglUseProgramObjectARB(0);CHECKGLERROR
813 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
815 Mem_Free(shaderstring);
818 void R_GLSL_Restart_f(void)
821 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
822 if (r_glsl_permutations[i].program)
823 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
824 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
827 extern rtexture_t *r_shadow_attenuationgradienttexture;
828 extern rtexture_t *r_shadow_attenuation2dtexture;
829 extern rtexture_t *r_shadow_attenuation3dtexture;
830 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
832 // select a permutation of the lighting shader appropriate to this
833 // combination of texture, entity, light source, and fogging, only use the
834 // minimum features necessary to avoid wasting rendering time in the
835 // fragment shader on features that are not being used
836 const char *shaderfilename = NULL;
837 unsigned int permutation = 0;
838 r_glsl_permutation = NULL;
839 // TODO: implement geometry-shader based shadow volumes someday
840 if (rsurface.rtlight)
843 shaderfilename = "glsl/default.glsl";
844 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
845 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
846 permutation |= SHADERPERMUTATION_CUBEFILTER;
847 if (diffusescale > 0)
848 permutation |= SHADERPERMUTATION_DIFFUSE;
849 if (specularscale > 0)
850 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
851 if (r_refdef.fogenabled)
852 permutation |= SHADERPERMUTATION_FOG;
853 if (rsurface.texture->colormapping)
854 permutation |= SHADERPERMUTATION_COLORMAPPING;
855 if (r_glsl_offsetmapping.integer)
857 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
858 if (r_glsl_offsetmapping_reliefmapping.integer)
859 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
861 if(r_glsl_contrastboost.value != 1 && r_glsl_contrastboost.value != 0)
862 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
864 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
866 // bright unshaded geometry
867 shaderfilename = "glsl/default.glsl";
868 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
869 if (rsurface.texture->currentskinframe->glow)
870 permutation |= SHADERPERMUTATION_GLOW;
871 if (r_refdef.fogenabled)
872 permutation |= SHADERPERMUTATION_FOG;
873 if (rsurface.texture->colormapping)
874 permutation |= SHADERPERMUTATION_COLORMAPPING;
875 if (r_glsl_offsetmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
878 if (r_glsl_offsetmapping_reliefmapping.integer)
879 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
881 if(r_glsl_contrastboost.value != 1 && r_glsl_contrastboost.value != 0)
882 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
884 else if (modellighting)
886 // directional model lighting
887 shaderfilename = "glsl/default.glsl";
888 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
889 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
890 if (rsurface.texture->currentskinframe->glow)
891 permutation |= SHADERPERMUTATION_GLOW;
892 if (specularscale > 0)
893 permutation |= SHADERPERMUTATION_SPECULAR;
894 if (r_refdef.fogenabled)
895 permutation |= SHADERPERMUTATION_FOG;
896 if (rsurface.texture->colormapping)
897 permutation |= SHADERPERMUTATION_COLORMAPPING;
898 if (r_glsl_offsetmapping.integer)
900 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
901 if (r_glsl_offsetmapping_reliefmapping.integer)
902 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
904 if(r_glsl_contrastboost.value != 1 && r_glsl_contrastboost.value != 0)
905 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
910 shaderfilename = "glsl/default.glsl";
911 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
912 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
914 // deluxemapping (light direction texture)
915 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
916 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
918 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
919 if (specularscale > 0)
920 permutation |= SHADERPERMUTATION_SPECULAR;
922 else if (r_glsl_deluxemapping.integer >= 2)
924 // fake deluxemapping (uniform light direction in tangentspace)
925 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
926 if (specularscale > 0)
927 permutation |= SHADERPERMUTATION_SPECULAR;
931 // ordinary lightmapping
934 if (rsurface.texture->currentskinframe->glow)
935 permutation |= SHADERPERMUTATION_GLOW;
936 if (r_refdef.fogenabled)
937 permutation |= SHADERPERMUTATION_FOG;
938 if (rsurface.texture->colormapping)
939 permutation |= SHADERPERMUTATION_COLORMAPPING;
940 if (r_glsl_offsetmapping.integer)
942 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
943 if (r_glsl_offsetmapping_reliefmapping.integer)
944 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
946 if(r_glsl_contrastboost.value != 1 && r_glsl_contrastboost.value != 0)
947 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
949 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
951 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
952 R_GLSL_CompilePermutation(shaderfilename, permutation);
953 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
955 // remove features until we find a valid permutation
957 for (i = SHADERPERMUTATION_MASK;;i>>=1)
960 return 0; // utterly failed
961 // reduce i more quickly whenever it would not remove any bits
965 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
966 R_GLSL_CompilePermutation(shaderfilename, permutation);
967 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
972 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
974 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
975 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
976 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
978 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
979 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
980 if (permutation & SHADERPERMUTATION_DIFFUSE)
982 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
983 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
984 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
985 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
989 // ambient only is simpler
990 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
991 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
992 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
993 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
996 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
998 if (r_glsl_permutation->loc_AmbientColor >= 0)
999 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1000 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1001 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1002 if (r_glsl_permutation->loc_SpecularColor >= 0)
1003 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1004 if (r_glsl_permutation->loc_LightDir >= 0)
1005 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1009 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1010 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1011 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1013 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
1014 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1015 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1016 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1017 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1018 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1019 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1020 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1021 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1022 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1023 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1024 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1025 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1027 // The formula used is actually:
1028 // color.rgb *= SceneBrightness;
1029 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1030 // I simplify that to
1031 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1032 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1034 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1035 // and do [[calculations]] here in the engine
1036 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1037 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1040 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1041 if (r_glsl_permutation->loc_FogColor >= 0)
1043 // additive passes are only darkened by fog, not tinted
1044 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1045 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1047 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1049 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1050 if (r_glsl_permutation->loc_Color_Pants >= 0)
1052 if (rsurface.texture->currentskinframe->pants)
1053 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1055 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1057 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1059 if (rsurface.texture->currentskinframe->shirt)
1060 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1062 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1064 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1065 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1066 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1071 void R_SwitchSurfaceShader(int permutation)
1073 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1075 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1077 qglUseProgramObjectARB(r_glsl_permutation->program);
1082 #define SKINFRAME_HASH 1024
1086 int loadsequence; // incremented each level change
1087 memexpandablearray_t array;
1088 skinframe_t *hash[SKINFRAME_HASH];
1092 void R_SkinFrame_PrepareForPurge(void)
1094 r_skinframe.loadsequence++;
1095 // wrap it without hitting zero
1096 if (r_skinframe.loadsequence >= 200)
1097 r_skinframe.loadsequence = 1;
1100 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1104 // mark the skinframe as used for the purging code
1105 skinframe->loadsequence = r_skinframe.loadsequence;
1108 void R_SkinFrame_Purge(void)
1112 for (i = 0;i < SKINFRAME_HASH;i++)
1114 for (s = r_skinframe.hash[i];s;s = s->next)
1116 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1118 if (s->base == r_texture_notexture) s->base = NULL;
1119 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1120 if (s->merged == s->base) s->merged = NULL;
1121 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1122 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1123 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1124 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1125 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1126 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1127 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1128 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1129 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1130 s->loadsequence = 0;
1136 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1140 char basename[MAX_QPATH];
1142 Image_StripImageExtension(name, basename, sizeof(basename));
1144 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1145 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1146 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1152 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1153 memset(item, 0, sizeof(*item));
1154 strlcpy(item->basename, basename, sizeof(item->basename));
1155 item->textureflags = textureflags;
1156 item->comparewidth = comparewidth;
1157 item->compareheight = compareheight;
1158 item->comparecrc = comparecrc;
1159 item->next = r_skinframe.hash[hashindex];
1160 r_skinframe.hash[hashindex] = item;
1162 R_SkinFrame_MarkUsed(item);
1166 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1168 // FIXME: it should be possible to disable loading various layers using
1169 // cvars, to prevent wasted loading time and memory usage if the user does
1171 qboolean loadnormalmap = true;
1172 qboolean loadgloss = true;
1173 qboolean loadpantsandshirt = true;
1174 qboolean loadglow = true;
1176 unsigned char *pixels;
1177 unsigned char *bumppixels;
1178 unsigned char *basepixels = NULL;
1179 int basepixels_width;
1180 int basepixels_height;
1181 skinframe_t *skinframe;
1183 if (cls.state == ca_dedicated)
1186 // return an existing skinframe if already loaded
1187 // if loading of the first image fails, don't make a new skinframe as it
1188 // would cause all future lookups of this to be missing
1189 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1190 if (skinframe && skinframe->base)
1193 basepixels = loadimagepixels(name, complain, 0, 0);
1194 if (basepixels == NULL)
1197 // we've got some pixels to store, so really allocate this new texture now
1199 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1200 skinframe->stain = NULL;
1201 skinframe->merged = NULL;
1202 skinframe->base = r_texture_notexture;
1203 skinframe->pants = NULL;
1204 skinframe->shirt = NULL;
1205 skinframe->nmap = r_texture_blanknormalmap;
1206 skinframe->gloss = NULL;
1207 skinframe->glow = NULL;
1208 skinframe->fog = NULL;
1210 basepixels_width = image_width;
1211 basepixels_height = image_height;
1212 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1214 if (textureflags & TEXF_ALPHA)
1216 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1217 if (basepixels[j] < 255)
1219 if (j < basepixels_width * basepixels_height * 4)
1221 // has transparent pixels
1222 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1223 for (j = 0;j < image_width * image_height * 4;j += 4)
1228 pixels[j+3] = basepixels[j+3];
1230 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1235 // _norm is the name used by tenebrae and has been adopted as standard
1238 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1240 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1244 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1246 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1247 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1248 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1250 Mem_Free(bumppixels);
1252 else if (r_shadow_bumpscale_basetexture.value > 0)
1254 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1255 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1256 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1260 // _luma is supported for tenebrae compatibility
1261 // (I think it's a very stupid name, but oh well)
1262 // _glow is the preferred name
1263 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;}
1264 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;}
1265 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;}
1266 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;}
1269 Mem_Free(basepixels);
1274 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)
1279 for (i = 0;i < width*height;i++)
1280 if (((unsigned char *)&palette[in[i]])[3] > 0)
1282 if (i == width*height)
1285 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1288 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)
1291 unsigned char *temp1, *temp2;
1292 skinframe_t *skinframe;
1294 if (cls.state == ca_dedicated)
1297 // if already loaded just return it, otherwise make a new skinframe
1298 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1299 if (skinframe && skinframe->base)
1302 skinframe->stain = NULL;
1303 skinframe->merged = NULL;
1304 skinframe->base = r_texture_notexture;
1305 skinframe->pants = NULL;
1306 skinframe->shirt = NULL;
1307 skinframe->nmap = r_texture_blanknormalmap;
1308 skinframe->gloss = NULL;
1309 skinframe->glow = NULL;
1310 skinframe->fog = NULL;
1312 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1316 if (bitsperpixel == 32)
1318 if (r_shadow_bumpscale_basetexture.value > 0)
1320 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1321 temp2 = temp1 + width * height * 4;
1322 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1323 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1326 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1327 if (textureflags & TEXF_ALPHA)
1329 for (i = 3;i < width * height * 4;i += 4)
1330 if (skindata[i] < 255)
1332 if (i < width * height * 4)
1334 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1335 memcpy(fogpixels, skindata, width * height * 4);
1336 for (i = 0;i < width * height * 4;i += 4)
1337 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1338 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1339 Mem_Free(fogpixels);
1343 else if (bitsperpixel == 8)
1345 if (r_shadow_bumpscale_basetexture.value > 0)
1347 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1348 temp2 = temp1 + width * height * 4;
1349 if (bitsperpixel == 32)
1350 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1353 // use either a custom palette or the quake palette
1354 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1355 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1357 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1360 // use either a custom palette, or the quake palette
1361 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
1362 if (!palette && loadglowtexture)
1363 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1364 if (!palette && loadpantsandshirt)
1366 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1367 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1369 if (skinframe->pants || skinframe->shirt)
1370 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1371 if (textureflags & TEXF_ALPHA)
1373 // if not using a custom alphapalette, use the quake one
1375 alphapalette = palette_alpha;
1376 for (i = 0;i < width * height;i++)
1377 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1379 if (i < width * height)
1380 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1387 skinframe_t *R_SkinFrame_LoadMissing(void)
1389 skinframe_t *skinframe;
1391 if (cls.state == ca_dedicated)
1394 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1395 skinframe->stain = NULL;
1396 skinframe->merged = NULL;
1397 skinframe->base = r_texture_notexture;
1398 skinframe->pants = NULL;
1399 skinframe->shirt = NULL;
1400 skinframe->nmap = r_texture_blanknormalmap;
1401 skinframe->gloss = NULL;
1402 skinframe->glow = NULL;
1403 skinframe->fog = NULL;
1408 void gl_main_start(void)
1413 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1414 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1416 alpha = 1 - exp(r / ((double)x*(double)x));
1417 if (x == FOGMASKTABLEWIDTH - 1)
1419 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1422 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1423 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1425 // set up r_skinframe loading system for textures
1426 memset(&r_skinframe, 0, sizeof(r_skinframe));
1427 r_skinframe.loadsequence = 1;
1428 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1430 r_main_texturepool = R_AllocTexturePool();
1431 R_BuildBlankTextures();
1433 if (gl_texturecubemap)
1436 R_BuildNormalizationCube();
1438 R_BuildFogTexture();
1439 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1440 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1441 memset(&r_svbsp, 0, sizeof (r_svbsp));
1444 void gl_main_shutdown(void)
1446 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1447 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1449 // clear out the r_skinframe state
1450 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1451 memset(&r_skinframe, 0, sizeof(r_skinframe));
1454 Mem_Free(r_svbsp.nodes);
1455 memset(&r_svbsp, 0, sizeof (r_svbsp));
1456 R_FreeTexturePool(&r_main_texturepool);
1457 r_texture_blanknormalmap = NULL;
1458 r_texture_white = NULL;
1459 r_texture_black = NULL;
1460 r_texture_whitecube = NULL;
1461 r_texture_normalizationcube = NULL;
1462 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1466 extern void CL_ParseEntityLump(char *entitystring);
1467 void gl_main_newmap(void)
1469 // FIXME: move this code to client
1471 char *entities, entname[MAX_QPATH];
1474 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1475 l = (int)strlen(entname) - 4;
1476 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1478 memcpy(entname + l, ".ent", 5);
1479 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1481 CL_ParseEntityLump(entities);
1486 if (cl.worldmodel->brush.entities)
1487 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1491 void GL_Main_Init(void)
1493 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1495 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1496 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1497 if (gamemode == GAME_NEHAHRA)
1499 Cvar_RegisterVariable (&gl_fogenable);
1500 Cvar_RegisterVariable (&gl_fogdensity);
1501 Cvar_RegisterVariable (&gl_fogred);
1502 Cvar_RegisterVariable (&gl_foggreen);
1503 Cvar_RegisterVariable (&gl_fogblue);
1504 Cvar_RegisterVariable (&gl_fogstart);
1505 Cvar_RegisterVariable (&gl_fogend);
1507 Cvar_RegisterVariable(&r_depthfirst);
1508 Cvar_RegisterVariable(&r_nearclip);
1509 Cvar_RegisterVariable(&r_showbboxes);
1510 Cvar_RegisterVariable(&r_showsurfaces);
1511 Cvar_RegisterVariable(&r_showtris);
1512 Cvar_RegisterVariable(&r_shownormals);
1513 Cvar_RegisterVariable(&r_showlighting);
1514 Cvar_RegisterVariable(&r_showshadowvolumes);
1515 Cvar_RegisterVariable(&r_showcollisionbrushes);
1516 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1517 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1518 Cvar_RegisterVariable(&r_showdisabledepthtest);
1519 Cvar_RegisterVariable(&r_drawportals);
1520 Cvar_RegisterVariable(&r_drawentities);
1521 Cvar_RegisterVariable(&r_cullentities_trace);
1522 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1523 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1524 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1525 Cvar_RegisterVariable(&r_drawviewmodel);
1526 Cvar_RegisterVariable(&r_speeds);
1527 Cvar_RegisterVariable(&r_fullbrights);
1528 Cvar_RegisterVariable(&r_wateralpha);
1529 Cvar_RegisterVariable(&r_dynamic);
1530 Cvar_RegisterVariable(&r_fullbright);
1531 Cvar_RegisterVariable(&r_shadows);
1532 Cvar_RegisterVariable(&r_shadows_throwdistance);
1533 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1534 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1535 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1536 Cvar_RegisterVariable(&r_textureunits);
1537 Cvar_RegisterVariable(&r_glsl);
1538 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1539 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1540 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1541 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1542 Cvar_RegisterVariable(&r_lerpsprites);
1543 Cvar_RegisterVariable(&r_lerpmodels);
1544 Cvar_RegisterVariable(&r_waterscroll);
1545 Cvar_RegisterVariable(&r_bloom);
1546 Cvar_RegisterVariable(&r_bloom_colorscale);
1547 Cvar_RegisterVariable(&r_bloom_brighten);
1548 Cvar_RegisterVariable(&r_bloom_blur);
1549 Cvar_RegisterVariable(&r_bloom_resolution);
1550 Cvar_RegisterVariable(&r_bloom_colorexponent);
1551 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1552 Cvar_RegisterVariable(&r_hdr);
1553 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1554 Cvar_RegisterVariable(&r_glsl_contrastboost);
1555 Cvar_RegisterVariable(&r_hdr_glowintensity);
1556 Cvar_RegisterVariable(&r_hdr_range);
1557 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1558 Cvar_RegisterVariable(&developer_texturelogging);
1559 Cvar_RegisterVariable(&gl_lightmaps);
1560 Cvar_RegisterVariable(&r_test);
1561 Cvar_RegisterVariable(&r_batchmode);
1562 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1563 Cvar_SetValue("r_fullbrights", 0);
1564 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1567 extern void R_Textures_Init(void);
1568 extern void GL_Draw_Init(void);
1569 extern void GL_Main_Init(void);
1570 extern void R_Shadow_Init(void);
1571 extern void R_Sky_Init(void);
1572 extern void GL_Surf_Init(void);
1573 extern void R_Light_Init(void);
1574 extern void R_Particles_Init(void);
1575 extern void R_Explosion_Init(void);
1576 extern void gl_backend_init(void);
1577 extern void Sbar_Init(void);
1578 extern void R_LightningBeams_Init(void);
1579 extern void Mod_RenderInit(void);
1581 void Render_Init(void)
1594 R_LightningBeams_Init();
1603 extern char *ENGINE_EXTENSIONS;
1606 VID_CheckExtensions();
1608 // LordHavoc: report supported extensions
1609 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1611 // clear to black (loading plaque will be seen over this)
1613 qglClearColor(0,0,0,1);CHECKGLERROR
1614 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1617 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1621 for (i = 0;i < 4;i++)
1623 p = r_view.frustum + i;
1628 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1632 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1636 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1640 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1644 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1648 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1652 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1656 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1664 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1668 for (i = 0;i < numplanes;i++)
1675 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1679 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1683 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1687 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1691 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1695 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1699 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1703 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1711 //==================================================================================
1713 static void R_UpdateEntityLighting(entity_render_t *ent)
1715 vec3_t tempdiffusenormal;
1717 // fetch the lighting from the worldmodel data
1718 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));
1719 VectorClear(ent->modellight_diffuse);
1720 VectorClear(tempdiffusenormal);
1721 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1724 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1725 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1728 VectorSet(ent->modellight_ambient, 1, 1, 1);
1730 // move the light direction into modelspace coordinates for lighting code
1731 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1732 if(VectorLength2(ent->modellight_lightdir) > 0)
1734 VectorNormalize(ent->modellight_lightdir);
1738 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1741 // scale ambient and directional light contributions according to rendering variables
1742 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1743 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1744 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1745 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1746 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1747 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1750 static void R_View_UpdateEntityVisible (void)
1753 entity_render_t *ent;
1755 if (!r_drawentities.integer)
1758 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1759 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1761 // worldmodel can check visibility
1762 for (i = 0;i < r_refdef.numentities;i++)
1764 ent = r_refdef.entities[i];
1765 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));
1767 if(r_cullentities_trace.integer)
1769 for (i = 0;i < r_refdef.numentities;i++)
1771 ent = r_refdef.entities[i];
1772 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1774 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1775 ent->last_trace_visibility = realtime;
1776 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1777 r_viewcache.entityvisible[i] = 0;
1784 // no worldmodel or it can't check visibility
1785 for (i = 0;i < r_refdef.numentities;i++)
1787 ent = r_refdef.entities[i];
1788 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1792 // update entity lighting (even on hidden entities for r_shadows)
1793 for (i = 0;i < r_refdef.numentities;i++)
1794 R_UpdateEntityLighting(r_refdef.entities[i]);
1797 // only used if skyrendermasked, and normally returns false
1798 int R_DrawBrushModelsSky (void)
1801 entity_render_t *ent;
1803 if (!r_drawentities.integer)
1807 for (i = 0;i < r_refdef.numentities;i++)
1809 if (!r_viewcache.entityvisible[i])
1811 ent = r_refdef.entities[i];
1812 if (!ent->model || !ent->model->DrawSky)
1814 ent->model->DrawSky(ent);
1820 void R_DrawNoModel(entity_render_t *ent);
1821 void R_DrawModels(void)
1824 entity_render_t *ent;
1826 if (!r_drawentities.integer)
1829 for (i = 0;i < r_refdef.numentities;i++)
1831 if (!r_viewcache.entityvisible[i])
1833 ent = r_refdef.entities[i];
1834 r_refdef.stats.entities++;
1835 if (ent->model && ent->model->Draw != NULL)
1836 ent->model->Draw(ent);
1842 void R_DrawModelsDepth(void)
1845 entity_render_t *ent;
1847 if (!r_drawentities.integer)
1850 for (i = 0;i < r_refdef.numentities;i++)
1852 if (!r_viewcache.entityvisible[i])
1854 ent = r_refdef.entities[i];
1855 r_refdef.stats.entities++;
1856 if (ent->model && ent->model->DrawDepth != NULL)
1857 ent->model->DrawDepth(ent);
1861 static void R_View_SetFrustum(void)
1863 double slopex, slopey;
1865 // break apart the view matrix into vectors for various purposes
1866 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1867 VectorNegate(r_view.left, r_view.right);
1870 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1871 r_view.frustum[0].normal[1] = 0 - 0;
1872 r_view.frustum[0].normal[2] = -1 - 0;
1873 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1874 r_view.frustum[1].normal[1] = 0 + 0;
1875 r_view.frustum[1].normal[2] = -1 + 0;
1876 r_view.frustum[2].normal[0] = 0 - 0;
1877 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1878 r_view.frustum[2].normal[2] = -1 - 0;
1879 r_view.frustum[3].normal[0] = 0 + 0;
1880 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1881 r_view.frustum[3].normal[2] = -1 + 0;
1885 zNear = r_refdef.nearclip;
1886 nudge = 1.0 - 1.0 / (1<<23);
1887 r_view.frustum[4].normal[0] = 0 - 0;
1888 r_view.frustum[4].normal[1] = 0 - 0;
1889 r_view.frustum[4].normal[2] = -1 - -nudge;
1890 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1891 r_view.frustum[5].normal[0] = 0 + 0;
1892 r_view.frustum[5].normal[1] = 0 + 0;
1893 r_view.frustum[5].normal[2] = -1 + -nudge;
1894 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1900 r_view.frustum[0].normal[0] = m[3] - m[0];
1901 r_view.frustum[0].normal[1] = m[7] - m[4];
1902 r_view.frustum[0].normal[2] = m[11] - m[8];
1903 r_view.frustum[0].dist = m[15] - m[12];
1905 r_view.frustum[1].normal[0] = m[3] + m[0];
1906 r_view.frustum[1].normal[1] = m[7] + m[4];
1907 r_view.frustum[1].normal[2] = m[11] + m[8];
1908 r_view.frustum[1].dist = m[15] + m[12];
1910 r_view.frustum[2].normal[0] = m[3] - m[1];
1911 r_view.frustum[2].normal[1] = m[7] - m[5];
1912 r_view.frustum[2].normal[2] = m[11] - m[9];
1913 r_view.frustum[2].dist = m[15] - m[13];
1915 r_view.frustum[3].normal[0] = m[3] + m[1];
1916 r_view.frustum[3].normal[1] = m[7] + m[5];
1917 r_view.frustum[3].normal[2] = m[11] + m[9];
1918 r_view.frustum[3].dist = m[15] + m[13];
1920 r_view.frustum[4].normal[0] = m[3] - m[2];
1921 r_view.frustum[4].normal[1] = m[7] - m[6];
1922 r_view.frustum[4].normal[2] = m[11] - m[10];
1923 r_view.frustum[4].dist = m[15] - m[14];
1925 r_view.frustum[5].normal[0] = m[3] + m[2];
1926 r_view.frustum[5].normal[1] = m[7] + m[6];
1927 r_view.frustum[5].normal[2] = m[11] + m[10];
1928 r_view.frustum[5].dist = m[15] + m[14];
1933 slopex = 1.0 / r_view.frustum_x;
1934 slopey = 1.0 / r_view.frustum_y;
1935 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1936 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1937 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1938 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1939 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1940 VectorNormalize(r_view.frustum[0].normal);
1941 VectorNormalize(r_view.frustum[1].normal);
1942 VectorNormalize(r_view.frustum[2].normal);
1943 VectorNormalize(r_view.frustum[3].normal);
1944 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1945 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1946 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1947 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1948 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1949 PlaneClassify(&r_view.frustum[0]);
1950 PlaneClassify(&r_view.frustum[1]);
1951 PlaneClassify(&r_view.frustum[2]);
1952 PlaneClassify(&r_view.frustum[3]);
1953 PlaneClassify(&r_view.frustum[4]);
1955 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1956 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1957 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1958 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1959 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1961 // LordHavoc: note to all quake engine coders, Quake had a special case
1962 // for 90 degrees which assumed a square view (wrong), so I removed it,
1963 // Quake2 has it disabled as well.
1965 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1966 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1967 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1968 //PlaneClassify(&frustum[0]);
1970 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1971 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1972 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1973 //PlaneClassify(&frustum[1]);
1975 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1976 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1977 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1978 //PlaneClassify(&frustum[2]);
1980 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1981 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1982 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1983 //PlaneClassify(&frustum[3]);
1986 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1987 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1988 //PlaneClassify(&frustum[4]);
1991 void R_View_Update(void)
1993 R_View_SetFrustum();
1994 R_View_WorldVisibility();
1995 R_View_UpdateEntityVisible();
1998 void R_SetupView(const matrix4x4_t *matrix)
2000 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2001 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2003 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2005 GL_SetupView_Orientation_FromEntity(matrix);
2008 void R_ResetViewRendering2D(void)
2010 if (gl_support_fragment_shader)
2012 qglUseProgramObjectARB(0);CHECKGLERROR
2017 // GL is weird because it's bottom to top, r_view.y is top to bottom
2018 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2019 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2020 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2021 GL_Color(1, 1, 1, 1);
2022 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2023 GL_BlendFunc(GL_ONE, GL_ZERO);
2024 GL_AlphaTest(false);
2025 GL_ScissorTest(false);
2026 GL_DepthMask(false);
2027 GL_DepthRange(0, 1);
2028 GL_DepthTest(false);
2029 R_Mesh_Matrix(&identitymatrix);
2030 R_Mesh_ResetTextureState();
2031 GL_PolygonOffset(0, 0);
2032 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2033 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2034 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2035 qglStencilMask(~0);CHECKGLERROR
2036 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2037 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2038 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2041 void R_ResetViewRendering3D(void)
2043 if (gl_support_fragment_shader)
2045 qglUseProgramObjectARB(0);CHECKGLERROR
2050 // GL is weird because it's bottom to top, r_view.y is top to bottom
2051 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2052 R_SetupView(&r_view.matrix);
2053 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2054 GL_Color(1, 1, 1, 1);
2055 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2056 GL_BlendFunc(GL_ONE, GL_ZERO);
2057 GL_AlphaTest(false);
2058 GL_ScissorTest(true);
2060 GL_DepthRange(0, 1);
2062 R_Mesh_Matrix(&identitymatrix);
2063 R_Mesh_ResetTextureState();
2064 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2065 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2066 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2067 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2068 qglStencilMask(~0);CHECKGLERROR
2069 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2070 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2071 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2075 R_Bloom_SetupShader(
2077 "// written by Forest 'LordHavoc' Hale\n"
2079 "// common definitions between vertex shader and fragment shader:\n"
2081 "#ifdef __GLSL_CG_DATA_TYPES\n"
2082 "#define myhalf half\n"
2083 "#define myhvec2 hvec2\n"
2084 "#define myhvec3 hvec3\n"
2085 "#define myhvec4 hvec4\n"
2087 "#define myhalf float\n"
2088 "#define myhvec2 vec2\n"
2089 "#define myhvec3 vec3\n"
2090 "#define myhvec4 vec4\n"
2093 "varying vec2 ScreenTexCoord;\n"
2094 "varying vec2 BloomTexCoord;\n"
2099 "// vertex shader specific:\n"
2100 "#ifdef VERTEX_SHADER\n"
2104 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2105 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2106 " // transform vertex to camera space, using ftransform to match non-VS\n"
2108 " gl_Position = ftransform();\n"
2111 "#endif // VERTEX_SHADER\n"
2116 "// fragment shader specific:\n"
2117 "#ifdef FRAGMENT_SHADER\n"
2122 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2123 " for (x = -BLUR_X;x <= BLUR_X;x++)
2124 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2125 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2126 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2127 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2129 " gl_FragColor = vec4(color);\n"
2132 "#endif // FRAGMENT_SHADER\n"
2135 void R_RenderScene(void);
2137 void R_Bloom_StartFrame(void)
2139 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2141 // set bloomwidth and bloomheight to the bloom resolution that will be
2142 // used (often less than the screen resolution for faster rendering)
2143 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2144 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2145 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2147 // calculate desired texture sizes
2148 if (gl_support_arb_texture_non_power_of_two)
2150 screentexturewidth = r_view.width;
2151 screentextureheight = r_view.height;
2152 bloomtexturewidth = r_bloomstate.bloomwidth;
2153 bloomtextureheight = r_bloomstate.bloomheight;
2157 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2158 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2159 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2160 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2165 screentexturewidth = screentextureheight = 0;
2167 else if (r_bloom.integer)
2172 screentexturewidth = screentextureheight = 0;
2173 bloomtexturewidth = bloomtextureheight = 0;
2176 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)
2178 // can't use bloom if the parameters are too weird
2179 // can't use bloom if the card does not support the texture size
2180 if (r_bloomstate.texture_screen)
2181 R_FreeTexture(r_bloomstate.texture_screen);
2182 if (r_bloomstate.texture_bloom)
2183 R_FreeTexture(r_bloomstate.texture_bloom);
2184 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2188 r_bloomstate.enabled = true;
2189 r_bloomstate.hdr = r_hdr.integer != 0;
2191 // allocate textures as needed
2192 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2194 if (r_bloomstate.texture_screen)
2195 R_FreeTexture(r_bloomstate.texture_screen);
2196 r_bloomstate.texture_screen = NULL;
2197 r_bloomstate.screentexturewidth = screentexturewidth;
2198 r_bloomstate.screentextureheight = screentextureheight;
2199 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2200 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);
2202 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2204 if (r_bloomstate.texture_bloom)
2205 R_FreeTexture(r_bloomstate.texture_bloom);
2206 r_bloomstate.texture_bloom = NULL;
2207 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2208 r_bloomstate.bloomtextureheight = bloomtextureheight;
2209 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2210 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);
2213 // set up a texcoord array for the full resolution screen image
2214 // (we have to keep this around to copy back during final render)
2215 r_bloomstate.screentexcoord2f[0] = 0;
2216 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2217 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2218 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2219 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2220 r_bloomstate.screentexcoord2f[5] = 0;
2221 r_bloomstate.screentexcoord2f[6] = 0;
2222 r_bloomstate.screentexcoord2f[7] = 0;
2224 // set up a texcoord array for the reduced resolution bloom image
2225 // (which will be additive blended over the screen image)
2226 r_bloomstate.bloomtexcoord2f[0] = 0;
2227 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2228 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2229 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2230 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2231 r_bloomstate.bloomtexcoord2f[5] = 0;
2232 r_bloomstate.bloomtexcoord2f[6] = 0;
2233 r_bloomstate.bloomtexcoord2f[7] = 0;
2236 void R_Bloom_CopyScreenTexture(float colorscale)
2238 r_refdef.stats.bloom++;
2240 R_ResetViewRendering2D();
2241 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2242 R_Mesh_ColorPointer(NULL, 0, 0);
2243 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2244 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2246 // copy view into the screen texture
2247 GL_ActiveTexture(0);
2249 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
2250 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2252 // now scale it down to the bloom texture size
2254 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2255 GL_BlendFunc(GL_ONE, GL_ZERO);
2256 GL_Color(colorscale, colorscale, colorscale, 1);
2257 // TODO: optimize with multitexture or GLSL
2258 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2259 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2261 // we now have a bloom image in the framebuffer
2262 // copy it into the bloom image texture for later processing
2263 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2264 GL_ActiveTexture(0);
2266 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
2267 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2270 void R_Bloom_CopyHDRTexture(void)
2272 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2273 GL_ActiveTexture(0);
2275 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
2276 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2279 void R_Bloom_MakeTexture(void)
2282 float xoffset, yoffset, r, brighten;
2284 r_refdef.stats.bloom++;
2286 R_ResetViewRendering2D();
2287 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2288 R_Mesh_ColorPointer(NULL, 0, 0);
2290 // we have a bloom image in the framebuffer
2292 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2294 for (x = 1;x < r_bloom_colorexponent.value;)
2297 r = bound(0, r_bloom_colorexponent.value / x, 1);
2298 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2299 GL_Color(r, r, r, 1);
2300 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2301 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2302 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2303 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2305 // copy the vertically blurred bloom view to a texture
2306 GL_ActiveTexture(0);
2308 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
2309 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2312 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2313 brighten = r_bloom_brighten.value;
2315 brighten *= r_hdr_range.value;
2316 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2317 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2319 for (dir = 0;dir < 2;dir++)
2321 // blend on at multiple vertical offsets to achieve a vertical blur
2322 // TODO: do offset blends using GLSL
2323 GL_BlendFunc(GL_ONE, GL_ZERO);
2324 for (x = -range;x <= range;x++)
2326 if (!dir){xoffset = 0;yoffset = x;}
2327 else {xoffset = x;yoffset = 0;}
2328 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2329 yoffset /= (float)r_bloomstate.bloomtextureheight;
2330 // compute a texcoord array with the specified x and y offset
2331 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2332 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2333 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2334 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2335 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2336 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2337 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2338 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2339 // this r value looks like a 'dot' particle, fading sharply to
2340 // black at the edges
2341 // (probably not realistic but looks good enough)
2342 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2343 //r = (dir ? 1.0f : brighten)/(range*2+1);
2344 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2345 GL_Color(r, r, r, 1);
2346 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2347 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2348 GL_BlendFunc(GL_ONE, GL_ONE);
2351 // copy the vertically blurred bloom view to a texture
2352 GL_ActiveTexture(0);
2354 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
2355 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2358 // apply subtract last
2359 // (just like it would be in a GLSL shader)
2360 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2362 GL_BlendFunc(GL_ONE, GL_ZERO);
2363 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2364 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2365 GL_Color(1, 1, 1, 1);
2366 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2367 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2369 GL_BlendFunc(GL_ONE, GL_ONE);
2370 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2371 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2372 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2373 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2374 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2375 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2376 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2378 // copy the darkened bloom view to a texture
2379 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2380 GL_ActiveTexture(0);
2382 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
2383 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2387 void R_HDR_RenderBloomTexture(void)
2389 int oldwidth, oldheight;
2391 oldwidth = r_view.width;
2392 oldheight = r_view.height;
2393 r_view.width = r_bloomstate.bloomwidth;
2394 r_view.height = r_bloomstate.bloomheight;
2396 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2397 // TODO: add exposure compensation features
2398 // TODO: add fp16 framebuffer support
2400 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2402 r_view.colorscale /= r_hdr_range.value;
2405 R_ResetViewRendering2D();
2407 R_Bloom_CopyHDRTexture();
2408 R_Bloom_MakeTexture();
2410 R_ResetViewRendering3D();
2413 if (r_timereport_active)
2414 R_TimeReport("clear");
2417 // restore the view settings
2418 r_view.width = oldwidth;
2419 r_view.height = oldheight;
2422 static void R_BlendView(void)
2424 if (r_bloomstate.enabled && r_bloomstate.hdr)
2426 // render high dynamic range bloom effect
2427 // the bloom texture was made earlier this render, so we just need to
2428 // blend it onto the screen...
2429 R_ResetViewRendering2D();
2430 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2431 R_Mesh_ColorPointer(NULL, 0, 0);
2432 GL_Color(1, 1, 1, 1);
2433 GL_BlendFunc(GL_ONE, GL_ONE);
2434 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2435 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2436 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2437 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2439 else if (r_bloomstate.enabled)
2441 // render simple bloom effect
2442 // copy the screen and shrink it and darken it for the bloom process
2443 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2444 // make the bloom texture
2445 R_Bloom_MakeTexture();
2446 // put the original screen image back in place and blend the bloom
2448 R_ResetViewRendering2D();
2449 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2450 R_Mesh_ColorPointer(NULL, 0, 0);
2451 GL_Color(1, 1, 1, 1);
2452 GL_BlendFunc(GL_ONE, GL_ZERO);
2453 // do both in one pass if possible
2454 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2455 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2456 if (r_textureunits.integer >= 2 && gl_combine.integer)
2458 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2459 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2460 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2464 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2465 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2466 // now blend on the bloom texture
2467 GL_BlendFunc(GL_ONE, GL_ONE);
2468 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2469 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2471 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2472 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2474 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2476 // apply a color tint to the whole view
2477 R_ResetViewRendering2D();
2478 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2479 R_Mesh_ColorPointer(NULL, 0, 0);
2480 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2481 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2482 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2486 void R_RenderScene(void);
2488 matrix4x4_t r_waterscrollmatrix;
2490 void R_UpdateVariables(void)
2494 r_refdef.farclip = 4096;
2495 if (r_refdef.worldmodel)
2496 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2497 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2499 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2500 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2501 r_refdef.polygonfactor = 0;
2502 r_refdef.polygonoffset = 0;
2503 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2504 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2506 r_refdef.rtworld = r_shadow_realtime_world.integer;
2507 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2508 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2509 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2510 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2511 if (r_showsurfaces.integer)
2513 r_refdef.rtworld = false;
2514 r_refdef.rtworldshadows = false;
2515 r_refdef.rtdlight = false;
2516 r_refdef.rtdlightshadows = false;
2517 r_refdef.lightmapintensity = 0;
2520 if (gamemode == GAME_NEHAHRA)
2522 if (gl_fogenable.integer)
2524 r_refdef.oldgl_fogenable = true;
2525 r_refdef.fog_density = gl_fogdensity.value;
2526 r_refdef.fog_red = gl_fogred.value;
2527 r_refdef.fog_green = gl_foggreen.value;
2528 r_refdef.fog_blue = gl_fogblue.value;
2530 else if (r_refdef.oldgl_fogenable)
2532 r_refdef.oldgl_fogenable = false;
2533 r_refdef.fog_density = 0;
2534 r_refdef.fog_red = 0;
2535 r_refdef.fog_green = 0;
2536 r_refdef.fog_blue = 0;
2539 if (r_refdef.fog_density)
2541 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2542 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2543 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2545 if (r_refdef.fog_density)
2547 r_refdef.fogenabled = true;
2548 // this is the point where the fog reaches 0.9986 alpha, which we
2549 // consider a good enough cutoff point for the texture
2550 // (0.9986 * 256 == 255.6)
2551 r_refdef.fogrange = 400 / r_refdef.fog_density;
2552 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2553 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2554 // fog color was already set
2557 r_refdef.fogenabled = false;
2565 void R_RenderView(void)
2567 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2568 return; //Host_Error ("R_RenderView: NULL worldmodel");
2570 R_Shadow_UpdateWorldLightSelection();
2573 if (r_timereport_active)
2574 R_TimeReport("setup");
2577 if (r_timereport_active)
2578 R_TimeReport("visibility");
2580 R_ResetViewRendering3D();
2583 if (r_timereport_active)
2584 R_TimeReport("clear");
2586 R_Bloom_StartFrame();
2588 // this produces a bloom texture to be used in R_BlendView() later
2590 R_HDR_RenderBloomTexture();
2592 r_view.colorscale = r_hdr_scenebrightness.value;
2596 if (r_timereport_active)
2597 R_TimeReport("blendview");
2599 GL_Scissor(0, 0, vid.width, vid.height);
2600 GL_ScissorTest(false);
2604 extern void R_DrawLightningBeams (void);
2605 extern void VM_CL_AddPolygonsToMeshQueue (void);
2606 extern void R_DrawPortals (void);
2607 extern cvar_t cl_locs_show;
2608 static void R_DrawLocs(void);
2609 static void R_DrawEntityBBoxes(void);
2610 void R_RenderScene(void)
2612 // don't let sound skip if going slow
2613 if (r_refdef.extraupdate)
2616 R_ResetViewRendering3D();
2618 R_MeshQueue_BeginScene();
2622 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);
2624 if (cl.csqc_vidvars.drawworld)
2626 // don't let sound skip if going slow
2627 if (r_refdef.extraupdate)
2630 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2632 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2633 if (r_timereport_active)
2634 R_TimeReport("worldsky");
2637 if (R_DrawBrushModelsSky() && r_timereport_active)
2638 R_TimeReport("bmodelsky");
2641 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2643 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2644 if (r_timereport_active)
2645 R_TimeReport("worlddepth");
2647 if (r_depthfirst.integer >= 2)
2649 R_DrawModelsDepth();
2650 if (r_timereport_active)
2651 R_TimeReport("modeldepth");
2654 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2656 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2657 if (r_timereport_active)
2658 R_TimeReport("world");
2661 // don't let sound skip if going slow
2662 if (r_refdef.extraupdate)
2666 if (r_timereport_active)
2667 R_TimeReport("models");
2669 // don't let sound skip if going slow
2670 if (r_refdef.extraupdate)
2673 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2675 R_DrawModelShadows();
2677 R_ResetViewRendering3D();
2679 // don't let sound skip if going slow
2680 if (r_refdef.extraupdate)
2684 R_ShadowVolumeLighting(false);
2685 if (r_timereport_active)
2686 R_TimeReport("rtlights");
2688 // don't let sound skip if going slow
2689 if (r_refdef.extraupdate)
2692 if (cl.csqc_vidvars.drawworld)
2694 R_DrawLightningBeams();
2695 if (r_timereport_active)
2696 R_TimeReport("lightning");
2699 if (r_timereport_active)
2700 R_TimeReport("particles");
2703 if (r_timereport_active)
2704 R_TimeReport("explosions");
2707 if (gl_support_fragment_shader)
2709 qglUseProgramObjectARB(0);CHECKGLERROR
2711 VM_CL_AddPolygonsToMeshQueue();
2713 if (cl_locs_show.integer)
2716 if (r_timereport_active)
2717 R_TimeReport("showlocs");
2720 if (r_drawportals.integer)
2723 if (r_timereport_active)
2724 R_TimeReport("portals");
2727 if (r_showbboxes.value > 0)
2729 R_DrawEntityBBoxes();
2730 if (r_timereport_active)
2731 R_TimeReport("bboxes");
2734 if (gl_support_fragment_shader)
2736 qglUseProgramObjectARB(0);CHECKGLERROR
2738 R_MeshQueue_RenderTransparent();
2739 if (r_timereport_active)
2740 R_TimeReport("drawtrans");
2742 if (gl_support_fragment_shader)
2744 qglUseProgramObjectARB(0);CHECKGLERROR
2747 if (cl.csqc_vidvars.drawworld)
2750 if (r_timereport_active)
2751 R_TimeReport("coronas");
2754 // don't let sound skip if going slow
2755 if (r_refdef.extraupdate)
2758 R_ResetViewRendering2D();
2761 static const int bboxelements[36] =
2771 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2774 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2775 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2776 GL_DepthMask(false);
2777 GL_DepthRange(0, 1);
2778 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2779 R_Mesh_Matrix(&identitymatrix);
2780 R_Mesh_ResetTextureState();
2782 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2783 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2784 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2785 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2786 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2787 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2788 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2789 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2790 R_FillColors(color4f, 8, cr, cg, cb, ca);
2791 if (r_refdef.fogenabled)
2793 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2795 f1 = FogPoint_World(v);
2797 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2798 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2799 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2802 R_Mesh_VertexPointer(vertex3f, 0, 0);
2803 R_Mesh_ColorPointer(color4f, 0, 0);
2804 R_Mesh_ResetTextureState();
2805 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2808 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2812 prvm_edict_t *edict;
2813 // this function draws bounding boxes of server entities
2817 for (i = 0;i < numsurfaces;i++)
2819 edict = PRVM_EDICT_NUM(surfacelist[i]);
2820 switch ((int)edict->fields.server->solid)
2822 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2823 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2824 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2825 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2826 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2827 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2829 color[3] *= r_showbboxes.value;
2830 color[3] = bound(0, color[3], 1);
2831 GL_DepthTest(!r_showdisabledepthtest.integer);
2832 GL_CullFace(GL_BACK);
2833 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2838 static void R_DrawEntityBBoxes(void)
2841 prvm_edict_t *edict;
2843 // this function draws bounding boxes of server entities
2847 for (i = 0;i < prog->num_edicts;i++)
2849 edict = PRVM_EDICT_NUM(i);
2850 if (edict->priv.server->free)
2852 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2853 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2858 int nomodelelements[24] =
2870 float nomodelvertex3f[6*3] =
2880 float nomodelcolor4f[6*4] =
2882 0.0f, 0.0f, 0.5f, 1.0f,
2883 0.0f, 0.0f, 0.5f, 1.0f,
2884 0.0f, 0.5f, 0.0f, 1.0f,
2885 0.0f, 0.5f, 0.0f, 1.0f,
2886 0.5f, 0.0f, 0.0f, 1.0f,
2887 0.5f, 0.0f, 0.0f, 1.0f
2890 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2895 // this is only called once per entity so numsurfaces is always 1, and
2896 // surfacelist is always {0}, so this code does not handle batches
2897 R_Mesh_Matrix(&ent->matrix);
2899 if (ent->flags & EF_ADDITIVE)
2901 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2902 GL_DepthMask(false);
2904 else if (ent->alpha < 1)
2906 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2907 GL_DepthMask(false);
2911 GL_BlendFunc(GL_ONE, GL_ZERO);
2914 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2915 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2916 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2917 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2918 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2919 if (r_refdef.fogenabled)
2922 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2923 R_Mesh_ColorPointer(color4f, 0, 0);
2924 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2925 f1 = FogPoint_World(org);
2927 for (i = 0, c = color4f;i < 6;i++, c += 4)
2929 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2930 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2931 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2935 else if (ent->alpha != 1)
2937 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2938 R_Mesh_ColorPointer(color4f, 0, 0);
2939 for (i = 0, c = color4f;i < 6;i++, c += 4)
2943 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2944 R_Mesh_ResetTextureState();
2945 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2948 void R_DrawNoModel(entity_render_t *ent)
2951 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2952 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2953 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2955 // R_DrawNoModelCallback(ent, 0);
2958 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2960 vec3_t right1, right2, diff, normal;
2962 VectorSubtract (org2, org1, normal);
2964 // calculate 'right' vector for start
2965 VectorSubtract (r_view.origin, org1, diff);
2966 CrossProduct (normal, diff, right1);
2967 VectorNormalize (right1);
2969 // calculate 'right' vector for end
2970 VectorSubtract (r_view.origin, org2, diff);
2971 CrossProduct (normal, diff, right2);
2972 VectorNormalize (right2);
2974 vert[ 0] = org1[0] + width * right1[0];
2975 vert[ 1] = org1[1] + width * right1[1];
2976 vert[ 2] = org1[2] + width * right1[2];
2977 vert[ 3] = org1[0] - width * right1[0];
2978 vert[ 4] = org1[1] - width * right1[1];
2979 vert[ 5] = org1[2] - width * right1[2];
2980 vert[ 6] = org2[0] - width * right2[0];
2981 vert[ 7] = org2[1] - width * right2[1];
2982 vert[ 8] = org2[2] - width * right2[2];
2983 vert[ 9] = org2[0] + width * right2[0];
2984 vert[10] = org2[1] + width * right2[1];
2985 vert[11] = org2[2] + width * right2[2];
2988 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2990 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)
2995 if (r_refdef.fogenabled)
2996 fog = FogPoint_World(origin);
2998 R_Mesh_Matrix(&identitymatrix);
2999 GL_BlendFunc(blendfunc1, blendfunc2);
3005 GL_CullFace(GL_BACK);
3008 GL_CullFace(GL_FRONT);
3010 GL_DepthMask(false);
3011 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3012 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3013 GL_DepthTest(!depthdisable);
3015 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3016 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3017 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3018 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3019 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3020 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3021 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3022 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3023 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3024 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3025 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3026 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3028 R_Mesh_VertexPointer(vertex3f, 0, 0);
3029 R_Mesh_ColorPointer(NULL, 0, 0);
3030 R_Mesh_ResetTextureState();
3031 R_Mesh_TexBind(0, R_GetTexture(texture));
3032 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3033 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3034 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3035 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3037 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3039 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3040 GL_BlendFunc(blendfunc1, GL_ONE);
3042 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);
3043 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3047 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3052 VectorSet(v, x, y, z);
3053 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3054 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3056 if (i == mesh->numvertices)
3058 if (mesh->numvertices < mesh->maxvertices)
3060 VectorCopy(v, vertex3f);
3061 mesh->numvertices++;
3063 return mesh->numvertices;
3069 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3073 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3074 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3075 e = mesh->element3i + mesh->numtriangles * 3;
3076 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3078 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3079 if (mesh->numtriangles < mesh->maxtriangles)
3084 mesh->numtriangles++;
3086 element[1] = element[2];
3090 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3094 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3095 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3096 e = mesh->element3i + mesh->numtriangles * 3;
3097 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3099 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3100 if (mesh->numtriangles < mesh->maxtriangles)
3105 mesh->numtriangles++;
3107 element[1] = element[2];
3111 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3112 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3114 int planenum, planenum2;
3117 mplane_t *plane, *plane2;
3119 double temppoints[2][256*3];
3120 // figure out how large a bounding box we need to properly compute this brush
3122 for (w = 0;w < numplanes;w++)
3123 maxdist = max(maxdist, planes[w].dist);
3124 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3125 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3126 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3130 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3131 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3133 if (planenum2 == planenum)
3135 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);
3138 if (tempnumpoints < 3)
3140 // generate elements forming a triangle fan for this polygon
3141 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3145 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3148 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3149 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3150 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);
3151 GL_LockArrays(0, brush->numpoints);
3152 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3153 GL_LockArrays(0, 0);
3156 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3159 if (!surface->num_collisiontriangles)
3161 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3162 i = (int)(((size_t)surface) / sizeof(msurface_t));
3163 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);
3164 GL_LockArrays(0, surface->num_collisionvertices);
3165 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3166 GL_LockArrays(0, 0);
3169 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)
3171 texturelayer_t *layer;
3172 layer = t->currentlayers + t->currentnumlayers++;
3174 layer->depthmask = depthmask;
3175 layer->blendfunc1 = blendfunc1;
3176 layer->blendfunc2 = blendfunc2;
3177 layer->texture = texture;
3178 layer->texmatrix = *matrix;
3179 layer->color[0] = r * r_view.colorscale;
3180 layer->color[1] = g * r_view.colorscale;
3181 layer->color[2] = b * r_view.colorscale;
3182 layer->color[3] = a;
3185 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3188 index = parms[2] + r_refdef.time * parms[3];
3189 index -= floor(index);
3193 case Q3WAVEFUNC_NONE:
3194 case Q3WAVEFUNC_NOISE:
3195 case Q3WAVEFUNC_COUNT:
3198 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3199 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3200 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3201 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3202 case Q3WAVEFUNC_TRIANGLE:
3204 f = index - floor(index);
3215 return (float)(parms[0] + parms[1] * f);
3218 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3221 model_t *model = ent->model;
3224 q3shaderinfo_layer_tcmod_t *tcmod;
3226 // switch to an alternate material if this is a q1bsp animated material
3228 texture_t *texture = t;
3229 int s = ent->skinnum;
3230 if ((unsigned int)s >= (unsigned int)model->numskins)
3232 if (model->skinscenes)
3234 if (model->skinscenes[s].framecount > 1)
3235 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3237 s = model->skinscenes[s].firstframe;
3240 t = t + s * model->num_surfaces;
3243 // use an alternate animation if the entity's frame is not 0,
3244 // and only if the texture has an alternate animation
3245 if (ent->frame != 0 && t->anim_total[1])
3246 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3248 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3250 texture->currentframe = t;
3253 // update currentskinframe to be a qw skin or animation frame
3254 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3256 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3258 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3259 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3260 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);
3262 t->currentskinframe = r_qwskincache_skinframe[i];
3263 if (t->currentskinframe == NULL)
3264 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3266 else if (t->numskinframes >= 2)
3267 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3268 if (t->backgroundnumskinframes >= 2)
3269 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3271 t->currentmaterialflags = t->basematerialflags;
3272 t->currentalpha = ent->alpha;
3273 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3274 t->currentalpha *= r_wateralpha.value;
3275 if (!(ent->flags & RENDER_LIGHT))
3276 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3277 if (ent->effects & EF_ADDITIVE)
3278 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3279 else if (t->currentalpha < 1)
3280 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3281 if (ent->effects & EF_DOUBLESIDED)
3282 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3283 if (ent->effects & EF_NODEPTHTEST)
3284 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3285 if (ent->flags & RENDER_VIEWMODEL)
3286 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3287 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3288 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3290 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3293 switch(tcmod->tcmod)
3297 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3298 matrix = r_waterscrollmatrix;
3300 matrix = identitymatrix;
3302 case Q3TCMOD_ENTITYTRANSLATE:
3303 // this is used in Q3 to allow the gamecode to control texcoord
3304 // scrolling on the entity, which is not supported in darkplaces yet.
3305 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3307 case Q3TCMOD_ROTATE:
3308 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3309 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3310 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3313 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3315 case Q3TCMOD_SCROLL:
3316 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3318 case Q3TCMOD_STRETCH:
3319 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3320 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3322 case Q3TCMOD_TRANSFORM:
3323 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3324 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3325 VectorSet(tcmat + 6, 0 , 0 , 1);
3326 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3327 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3329 case Q3TCMOD_TURBULENT:
3330 // this is handled in the RSurf_PrepareVertices function
3331 matrix = identitymatrix;
3334 // either replace or concatenate the transformation
3336 t->currenttexmatrix = matrix;
3339 matrix4x4_t temp = t->currenttexmatrix;
3340 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3344 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3345 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3346 t->glosstexture = r_texture_white;
3347 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3348 t->backgroundglosstexture = r_texture_white;
3349 t->specularpower = r_shadow_glossexponent.value;
3350 // TODO: store reference values for these in the texture?
3351 t->specularscale = 0;
3352 if (r_shadow_gloss.integer > 0)
3354 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3356 if (r_shadow_glossintensity.value > 0)
3358 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3359 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3360 t->specularscale = r_shadow_glossintensity.value;
3363 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3364 t->specularscale = r_shadow_gloss2intensity.value;
3367 t->currentpolygonfactor = r_refdef.polygonfactor;
3368 t->currentpolygonoffset = r_refdef.polygonoffset;
3369 // submodels are biased to avoid z-fighting with world surfaces that they
3370 // may be exactly overlapping (avoids z-fighting artifacts on certain
3371 // doors and things in Quake maps)
3372 if (ent->model->brush.submodel)
3374 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3375 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3378 VectorClear(t->dlightcolor);
3379 t->currentnumlayers = 0;
3380 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3382 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3384 int blendfunc1, blendfunc2, depthmask;
3385 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3387 blendfunc1 = GL_SRC_ALPHA;
3388 blendfunc2 = GL_ONE;
3390 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3392 blendfunc1 = GL_SRC_ALPHA;
3393 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3395 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3397 blendfunc1 = t->customblendfunc[0];
3398 blendfunc2 = t->customblendfunc[1];
3402 blendfunc1 = GL_ONE;
3403 blendfunc2 = GL_ZERO;
3405 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3406 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3408 rtexture_t *currentbasetexture;
3410 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3411 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3412 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3413 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3415 // fullbright is not affected by r_refdef.lightmapintensity
3416 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3417 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3418 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);
3419 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3420 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);
3425 // set the color tint used for lights affecting this surface
3426 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3428 // q3bsp has no lightmap updates, so the lightstylevalue that
3429 // would normally be baked into the lightmap must be
3430 // applied to the color
3431 if (ent->model->type == mod_brushq3)
3432 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3433 colorscale *= r_refdef.lightmapintensity;
3434 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);
3435 if (r_ambient.value >= (1.0f/64.0f))
3436 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);
3437 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3439 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);
3440 if (r_ambient.value >= (1.0f/64.0f))
3441 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);
3443 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3445 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);
3446 if (r_ambient.value >= (1.0f/64.0f))
3447 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);
3450 if (t->currentskinframe->glow != NULL)
3451 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);
3452 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3454 // if this is opaque use alpha blend which will darken the earlier
3457 // if this is an alpha blended material, all the earlier passes
3458 // were darkened by fog already, so we only need to add the fog
3459 // color ontop through the fog mask texture
3461 // if this is an additive blended material, all the earlier passes
3462 // were darkened by fog already, and we should not add fog color
3463 // (because the background was not darkened, there is no fog color
3464 // that was lost behind it).
3465 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);
3472 void R_UpdateAllTextureInfo(entity_render_t *ent)
3476 for (i = 0;i < ent->model->num_texturesperskin;i++)
3477 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3480 rsurfacestate_t rsurface;
3482 void R_Mesh_ResizeArrays(int newvertices)
3485 if (rsurface.array_size >= newvertices)
3487 if (rsurface.array_modelvertex3f)
3488 Mem_Free(rsurface.array_modelvertex3f);
3489 rsurface.array_size = (newvertices + 1023) & ~1023;
3490 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3491 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3492 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3493 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3494 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3495 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3496 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3497 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3498 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3499 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3500 rsurface.array_color4f = base + rsurface.array_size * 27;
3501 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3504 void RSurf_CleanUp(void)
3507 if (rsurface.mode == RSURFMODE_GLSL)
3509 qglUseProgramObjectARB(0);CHECKGLERROR
3511 GL_AlphaTest(false);
3512 rsurface.mode = RSURFMODE_NONE;
3513 rsurface.uselightmaptexture = false;
3514 rsurface.texture = NULL;
3517 void RSurf_ActiveWorldEntity(void)
3519 model_t *model = r_refdef.worldmodel;
3521 if (rsurface.array_size < model->surfmesh.num_vertices)
3522 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3523 rsurface.matrix = identitymatrix;
3524 rsurface.inversematrix = identitymatrix;
3525 R_Mesh_Matrix(&identitymatrix);
3526 VectorCopy(r_view.origin, rsurface.modelorg);
3527 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3528 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3529 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3530 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3531 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3532 rsurface.frameblend[0].frame = 0;
3533 rsurface.frameblend[0].lerp = 1;
3534 rsurface.frameblend[1].frame = 0;
3535 rsurface.frameblend[1].lerp = 0;
3536 rsurface.frameblend[2].frame = 0;
3537 rsurface.frameblend[2].lerp = 0;
3538 rsurface.frameblend[3].frame = 0;
3539 rsurface.frameblend[3].lerp = 0;
3540 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3541 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3542 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3543 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3544 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3545 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3546 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3547 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3548 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3549 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3550 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3551 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3552 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3553 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3554 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3555 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3556 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3557 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3558 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3559 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3560 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3561 rsurface.modelelement3i = model->surfmesh.data_element3i;
3562 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3563 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3564 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3565 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3566 rsurface.modelsurfaces = model->data_surfaces;
3567 rsurface.generatedvertex = false;
3568 rsurface.vertex3f = rsurface.modelvertex3f;
3569 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3570 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3571 rsurface.svector3f = rsurface.modelsvector3f;
3572 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3573 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3574 rsurface.tvector3f = rsurface.modeltvector3f;
3575 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3576 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3577 rsurface.normal3f = rsurface.modelnormal3f;
3578 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3579 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3580 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3583 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3585 model_t *model = ent->model;
3587 if (rsurface.array_size < model->surfmesh.num_vertices)
3588 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3589 rsurface.matrix = ent->matrix;
3590 rsurface.inversematrix = ent->inversematrix;
3591 R_Mesh_Matrix(&rsurface.matrix);
3592 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3593 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3594 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3595 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3596 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3597 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3598 rsurface.frameblend[0] = ent->frameblend[0];
3599 rsurface.frameblend[1] = ent->frameblend[1];
3600 rsurface.frameblend[2] = ent->frameblend[2];
3601 rsurface.frameblend[3] = ent->frameblend[3];
3602 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3606 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3607 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3608 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3609 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3610 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3612 else if (wantnormals)
3614 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3615 rsurface.modelsvector3f = NULL;
3616 rsurface.modeltvector3f = NULL;
3617 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3618 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3622 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3623 rsurface.modelsvector3f = NULL;
3624 rsurface.modeltvector3f = NULL;
3625 rsurface.modelnormal3f = NULL;
3626 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3628 rsurface.modelvertex3f_bufferobject = 0;
3629 rsurface.modelvertex3f_bufferoffset = 0;
3630 rsurface.modelsvector3f_bufferobject = 0;
3631 rsurface.modelsvector3f_bufferoffset = 0;
3632 rsurface.modeltvector3f_bufferobject = 0;
3633 rsurface.modeltvector3f_bufferoffset = 0;
3634 rsurface.modelnormal3f_bufferobject = 0;
3635 rsurface.modelnormal3f_bufferoffset = 0;
3636 rsurface.generatedvertex = true;
3640 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3641 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3642 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3643 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3644 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3645 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3646 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3647 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3648 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3649 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3650 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3651 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3652 rsurface.generatedvertex = false;
3654 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3655 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3656 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3657 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3658 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3659 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3660 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3661 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3662 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3663 rsurface.modelelement3i = model->surfmesh.data_element3i;
3664 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3665 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3666 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3667 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3668 rsurface.modelsurfaces = model->data_surfaces;
3669 rsurface.vertex3f = rsurface.modelvertex3f;
3670 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3671 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3672 rsurface.svector3f = rsurface.modelsvector3f;
3673 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3674 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3675 rsurface.tvector3f = rsurface.modeltvector3f;
3676 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3677 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3678 rsurface.normal3f = rsurface.modelnormal3f;
3679 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3680 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3681 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3684 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3685 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3688 int texturesurfaceindex;
3693 const float *v1, *in_tc;
3695 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3697 q3shaderinfo_deform_t *deform;
3698 // 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
3699 if (rsurface.generatedvertex)
3701 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3702 generatenormals = true;
3703 for (i = 0;i < Q3MAXDEFORMS;i++)
3705 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3707 generatetangents = true;
3708 generatenormals = true;
3710 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3711 generatenormals = true;
3713 if (generatenormals && !rsurface.modelnormal3f)
3715 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3716 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3717 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3718 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3720 if (generatetangents && !rsurface.modelsvector3f)
3722 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3723 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3724 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3725 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3726 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3727 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3728 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);
3731 rsurface.vertex3f = rsurface.modelvertex3f;
3732 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3733 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3734 rsurface.svector3f = rsurface.modelsvector3f;
3735 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3736 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3737 rsurface.tvector3f = rsurface.modeltvector3f;
3738 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3739 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3740 rsurface.normal3f = rsurface.modelnormal3f;
3741 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3742 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3743 // if vertices are deformed (sprite flares and things in maps, possibly
3744 // water waves, bulges and other deformations), generate them into
3745 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3746 // (may be static model data or generated data for an animated model, or
3747 // the previous deform pass)
3748 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3750 switch (deform->deform)
3753 case Q3DEFORM_PROJECTIONSHADOW:
3754 case Q3DEFORM_TEXT0:
3755 case Q3DEFORM_TEXT1:
3756 case Q3DEFORM_TEXT2:
3757 case Q3DEFORM_TEXT3:
3758 case Q3DEFORM_TEXT4:
3759 case Q3DEFORM_TEXT5:
3760 case Q3DEFORM_TEXT6:
3761 case Q3DEFORM_TEXT7:
3764 case Q3DEFORM_AUTOSPRITE:
3765 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3766 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3767 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3768 VectorNormalize(newforward);
3769 VectorNormalize(newright);
3770 VectorNormalize(newup);
3771 // make deformed versions of only the model vertices used by the specified surfaces
3772 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3774 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3775 // a single autosprite surface can contain multiple sprites...
3776 for (j = 0;j < surface->num_vertices - 3;j += 4)
3778 VectorClear(center);
3779 for (i = 0;i < 4;i++)
3780 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3781 VectorScale(center, 0.25f, center);
3782 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3783 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3784 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3785 for (i = 0;i < 4;i++)
3787 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3788 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3791 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);
3792 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);
3794 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3795 rsurface.vertex3f_bufferobject = 0;
3796 rsurface.vertex3f_bufferoffset = 0;
3797 rsurface.svector3f = rsurface.array_deformedsvector3f;
3798 rsurface.svector3f_bufferobject = 0;
3799 rsurface.svector3f_bufferoffset = 0;
3800 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3801 rsurface.tvector3f_bufferobject = 0;
3802 rsurface.tvector3f_bufferoffset = 0;
3803 rsurface.normal3f = rsurface.array_deformednormal3f;
3804 rsurface.normal3f_bufferobject = 0;
3805 rsurface.normal3f_bufferoffset = 0;
3807 case Q3DEFORM_AUTOSPRITE2:
3808 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3809 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3810 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3811 VectorNormalize(newforward);
3812 VectorNormalize(newright);
3813 VectorNormalize(newup);
3814 // make deformed versions of only the model vertices used by the specified surfaces
3815 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3817 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3818 const float *v1, *v2;
3826 // a single autosprite surface can contain multiple sprites...
3827 for (j = 0;j < surface->num_vertices - 3;j += 4)
3829 VectorClear(center);
3830 for (i = 0;i < 4;i++)
3831 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3832 VectorScale(center, 0.25f, center);
3833 shortest[0].quadedge = shortest[1].quadedge = 0;
3834 shortest[0].length2 = shortest[1].length2 = 0;
3835 // find the two shortest edges, then use them to define the
3836 // axis vectors for rotating around the central axis
3837 for (i = 0;i < 6;i++)
3839 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3840 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3841 l = VectorDistance2(v1, v2);
3842 if (shortest[0].length2 > l || i == 0)
3844 shortest[1] = shortest[0];
3845 shortest[0].length2 = l;
3846 shortest[0].quadedge = i;
3848 else if (shortest[1].length2 > l || i == 1)
3850 shortest[1].length2 = l;
3851 shortest[1].quadedge = i;
3854 // this calculates the midpoints *2 (not bothering to average) of the two shortest edges, and subtracts one from the other to get the up vector
3855 for (i = 0;i < 3;i++)
3857 right[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
3858 + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i];
3859 up[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]
3860 + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i]
3861 - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i]
3862 - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i];
3864 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3865 VectorSubtract(rsurface.modelorg, center, forward);
3866 CrossProduct(up, forward, newright);
3867 // normalize the vectors involved
3868 VectorNormalize(right);
3869 VectorNormalize(newright);
3870 // rotate the quad around the up axis vector, this is made
3871 // especially easy by the fact we know the quad is flat,
3872 // so we only have to subtract the center position and
3873 // measure distance along the right vector, and then
3874 // multiply that by the newright vector and add back the
3876 // we also need to subtract the old position to undo the
3877 // displacement from the center, which we do with a
3878 // DotProduct, the subtraction/addition of center is also
3879 // optimized into DotProducts here
3880 l = DotProduct(newright, center) - DotProduct(right, center);
3881 for (i = 0;i < 4;i++)
3883 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3884 f = DotProduct(right, v1) - DotProduct(newright, v1) + l;
3885 VectorMA(v1, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3888 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);
3889 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);
3891 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3892 rsurface.vertex3f_bufferobject = 0;
3893 rsurface.vertex3f_bufferoffset = 0;
3894 rsurface.svector3f = rsurface.array_deformedsvector3f;
3895 rsurface.svector3f_bufferobject = 0;
3896 rsurface.svector3f_bufferoffset = 0;
3897 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3898 rsurface.tvector3f_bufferobject = 0;
3899 rsurface.tvector3f_bufferoffset = 0;
3900 rsurface.normal3f = rsurface.array_deformednormal3f;
3901 rsurface.normal3f_bufferobject = 0;
3902 rsurface.normal3f_bufferoffset = 0;
3904 case Q3DEFORM_NORMAL:
3905 // deform the normals to make reflections wavey
3906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3908 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3909 for (j = 0;j < surface->num_vertices;j++)
3912 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
3913 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
3914 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
3915 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3916 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3917 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3918 VectorNormalize(normal);
3920 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);
3922 rsurface.svector3f = rsurface.array_deformedsvector3f;
3923 rsurface.svector3f_bufferobject = 0;
3924 rsurface.svector3f_bufferoffset = 0;
3925 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3926 rsurface.tvector3f_bufferobject = 0;
3927 rsurface.tvector3f_bufferoffset = 0;
3928 rsurface.normal3f = rsurface.array_deformednormal3f;
3929 rsurface.normal3f_bufferobject = 0;
3930 rsurface.normal3f_bufferoffset = 0;
3933 // deform vertex array to make wavey water and flags and such
3934 waveparms[0] = deform->waveparms[0];
3935 waveparms[1] = deform->waveparms[1];
3936 waveparms[2] = deform->waveparms[2];
3937 waveparms[3] = deform->waveparms[3];
3938 // this is how a divisor of vertex influence on deformation
3939 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
3940 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
3941 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3943 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3944 for (j = 0;j < surface->num_vertices;j++)
3946 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
3947 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
3948 // if the wavefunc depends on time, evaluate it per-vertex
3951 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
3952 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
3954 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
3957 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3958 rsurface.vertex3f_bufferobject = 0;
3959 rsurface.vertex3f_bufferoffset = 0;
3961 case Q3DEFORM_BULGE:
3962 // deform vertex array to make the surface have moving bulges
3963 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3965 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3966 for (j = 0;j < surface->num_vertices;j++)
3968 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
3969 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
3972 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3973 rsurface.vertex3f_bufferobject = 0;
3974 rsurface.vertex3f_bufferoffset = 0;
3977 // deform vertex array
3978 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
3979 VectorScale(deform->parms, scale, waveparms);
3980 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3982 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3983 for (j = 0;j < surface->num_vertices;j++)
3984 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
3986 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3987 rsurface.vertex3f_bufferobject = 0;
3988 rsurface.vertex3f_bufferoffset = 0;
3992 // generate texcoords based on the chosen texcoord source
3993 switch(rsurface.texture->tcgen.tcgen)
3996 case Q3TCGEN_TEXTURE:
3997 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3998 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
3999 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4001 case Q3TCGEN_LIGHTMAP:
4002 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4003 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4004 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4006 case Q3TCGEN_VECTOR:
4007 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4009 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4010 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)
4012 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4013 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4016 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4017 rsurface.texcoordtexture2f_bufferobject = 0;
4018 rsurface.texcoordtexture2f_bufferoffset = 0;
4020 case Q3TCGEN_ENVIRONMENT:
4021 // make environment reflections using a spheremap
4022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4025 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4026 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4027 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4028 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4030 float l, d, eyedir[3];
4031 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4032 l = 0.5f / VectorLength(eyedir);
4033 d = DotProduct(normal, eyedir)*2;
4034 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4035 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4038 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4039 rsurface.texcoordtexture2f_bufferobject = 0;
4040 rsurface.texcoordtexture2f_bufferoffset = 0;
4043 // the only tcmod that needs software vertex processing is turbulent, so
4044 // check for it here and apply the changes if needed
4045 // and we only support that as the first one
4046 // (handling a mixture of turbulent and other tcmods would be problematic
4047 // without punting it entirely to a software path)
4048 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4050 amplitude = rsurface.texture->tcmods[0].parms[1];
4051 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4054 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4055 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)
4057 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4058 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4061 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4062 rsurface.texcoordtexture2f_bufferobject = 0;
4063 rsurface.texcoordtexture2f_bufferoffset = 0;
4065 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4066 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4067 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4068 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4071 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4074 const msurface_t *surface = texturesurfacelist[0];
4075 const msurface_t *surface2;
4080 // TODO: lock all array ranges before render, rather than on each surface
4081 if (texturenumsurfaces == 1)
4083 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4084 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));
4086 else if (r_batchmode.integer == 2)
4088 #define MAXBATCHTRIANGLES 4096
4089 int batchtriangles = 0;
4090 int batchelements[MAXBATCHTRIANGLES*3];
4091 for (i = 0;i < texturenumsurfaces;i = j)
4093 surface = texturesurfacelist[i];
4095 if (surface->num_triangles > MAXBATCHTRIANGLES)
4097 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));
4100 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4101 batchtriangles = surface->num_triangles;
4102 firstvertex = surface->num_firstvertex;
4103 endvertex = surface->num_firstvertex + surface->num_vertices;
4104 for (;j < texturenumsurfaces;j++)
4106 surface2 = texturesurfacelist[j];
4107 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4109 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4110 batchtriangles += surface2->num_triangles;
4111 firstvertex = min(firstvertex, surface2->num_firstvertex);
4112 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4114 surface2 = texturesurfacelist[j-1];
4115 numvertices = endvertex - firstvertex;
4116 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4119 else if (r_batchmode.integer == 1)
4121 for (i = 0;i < texturenumsurfaces;i = j)
4123 surface = texturesurfacelist[i];
4124 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4125 if (texturesurfacelist[j] != surface2)
4127 surface2 = texturesurfacelist[j-1];
4128 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4129 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4130 GL_LockArrays(surface->num_firstvertex, numvertices);
4131 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4136 for (i = 0;i < texturenumsurfaces;i++)
4138 surface = texturesurfacelist[i];
4139 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4140 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));
4145 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4149 const msurface_t *surface = texturesurfacelist[0];
4150 const msurface_t *surface2;
4155 // TODO: lock all array ranges before render, rather than on each surface
4156 if (texturenumsurfaces == 1)
4158 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4159 if (deluxemaptexunit >= 0)
4160 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4161 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4162 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));
4164 else if (r_batchmode.integer == 2)
4166 #define MAXBATCHTRIANGLES 4096
4167 int batchtriangles = 0;
4168 int batchelements[MAXBATCHTRIANGLES*3];
4169 for (i = 0;i < texturenumsurfaces;i = j)
4171 surface = texturesurfacelist[i];
4172 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4173 if (deluxemaptexunit >= 0)
4174 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4176 if (surface->num_triangles > MAXBATCHTRIANGLES)
4178 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));
4181 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4182 batchtriangles = surface->num_triangles;
4183 firstvertex = surface->num_firstvertex;
4184 endvertex = surface->num_firstvertex + surface->num_vertices;
4185 for (;j < texturenumsurfaces;j++)
4187 surface2 = texturesurfacelist[j];
4188 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4190 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4191 batchtriangles += surface2->num_triangles;
4192 firstvertex = min(firstvertex, surface2->num_firstvertex);
4193 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4195 surface2 = texturesurfacelist[j-1];
4196 numvertices = endvertex - firstvertex;
4197 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4200 else if (r_batchmode.integer == 1)
4203 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4204 for (i = 0;i < texturenumsurfaces;i = j)
4206 surface = texturesurfacelist[i];
4207 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4208 if (texturesurfacelist[j] != surface2)
4210 Con_Printf(" %i", j - i);
4213 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4215 for (i = 0;i < texturenumsurfaces;i = j)
4217 surface = texturesurfacelist[i];
4218 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4219 if (deluxemaptexunit >= 0)
4220 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4221 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4222 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4225 Con_Printf(" %i", j - i);
4227 surface2 = texturesurfacelist[j-1];
4228 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4229 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4230 GL_LockArrays(surface->num_firstvertex, numvertices);
4231 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4239 for (i = 0;i < texturenumsurfaces;i++)
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));
4245 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4246 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 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4254 int texturesurfaceindex;
4255 if (r_showsurfaces.integer == 2)
4257 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4259 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4260 for (j = 0;j < surface->num_triangles;j++)
4262 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4263 GL_Color(f, f, f, 1);
4264 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)));
4270 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4272 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4273 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4274 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);
4275 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4276 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));
4281 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4283 int texturesurfaceindex;
4287 if (rsurface.lightmapcolor4f)
4289 // generate color arrays for the surfaces in this list
4290 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4292 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4293 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)
4295 f = FogPoint_Model(v);
4305 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4308 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)
4310 f = FogPoint_Model(v);
4318 rsurface.lightmapcolor4f = rsurface.array_color4f;
4319 rsurface.lightmapcolor4f_bufferobject = 0;
4320 rsurface.lightmapcolor4f_bufferoffset = 0;
4323 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4325 int texturesurfaceindex;
4328 if (!rsurface.lightmapcolor4f)
4330 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4332 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4333 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)
4341 rsurface.lightmapcolor4f = rsurface.array_color4f;
4342 rsurface.lightmapcolor4f_bufferobject = 0;
4343 rsurface.lightmapcolor4f_bufferoffset = 0;
4346 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4349 rsurface.lightmapcolor4f = NULL;
4350 rsurface.lightmapcolor4f_bufferobject = 0;
4351 rsurface.lightmapcolor4f_bufferoffset = 0;
4352 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4353 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4354 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4355 GL_Color(r, g, b, a);
4356 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4359 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4361 // TODO: optimize applyfog && applycolor case
4362 // just apply fog if necessary, and tint the fog color array if necessary
4363 rsurface.lightmapcolor4f = NULL;
4364 rsurface.lightmapcolor4f_bufferobject = 0;
4365 rsurface.lightmapcolor4f_bufferoffset = 0;
4366 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4367 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4368 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4369 GL_Color(r, g, b, a);
4370 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4373 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4375 int texturesurfaceindex;
4379 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4381 // generate color arrays for the surfaces in this list
4382 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4384 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4385 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4387 if (surface->lightmapinfo->samples)
4389 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4390 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4391 VectorScale(lm, scale, c);
4392 if (surface->lightmapinfo->styles[1] != 255)
4394 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4396 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4397 VectorMA(c, scale, lm, c);
4398 if (surface->lightmapinfo->styles[2] != 255)
4401 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4402 VectorMA(c, scale, lm, c);
4403 if (surface->lightmapinfo->styles[3] != 255)
4406 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4407 VectorMA(c, scale, lm, c);
4417 rsurface.lightmapcolor4f = rsurface.array_color4f;
4418 rsurface.lightmapcolor4f_bufferobject = 0;
4419 rsurface.lightmapcolor4f_bufferoffset = 0;
4423 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4424 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4425 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4427 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4428 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4429 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4430 GL_Color(r, g, b, a);
4431 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4434 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4436 int texturesurfaceindex;
4440 vec3_t ambientcolor;
4441 vec3_t diffusecolor;
4445 VectorCopy(rsurface.modellight_lightdir, lightdir);
4446 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4447 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4448 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4449 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4450 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4451 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4452 if (VectorLength2(diffusecolor) > 0)
4454 // generate color arrays for the surfaces in this list
4455 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4457 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4458 int numverts = surface->num_vertices;
4459 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4460 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4461 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4462 // q3-style directional shading
4463 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4465 if ((f = DotProduct(c2, lightdir)) > 0)
4466 VectorMA(ambientcolor, f, diffusecolor, c);
4468 VectorCopy(ambientcolor, c);
4477 rsurface.lightmapcolor4f = rsurface.array_color4f;
4478 rsurface.lightmapcolor4f_bufferobject = 0;
4479 rsurface.lightmapcolor4f_bufferoffset = 0;
4483 r = ambientcolor[0];
4484 g = ambientcolor[1];
4485 b = ambientcolor[2];
4486 rsurface.lightmapcolor4f = NULL;
4487 rsurface.lightmapcolor4f_bufferobject = 0;
4488 rsurface.lightmapcolor4f_bufferoffset = 0;
4490 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4491 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4492 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4493 GL_Color(r, g, b, a);
4494 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4497 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4499 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4500 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4501 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4502 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4503 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4505 rsurface.mode = RSURFMODE_SHOWSURFACES;
4507 GL_BlendFunc(GL_ONE, GL_ZERO);
4508 R_Mesh_ColorPointer(NULL, 0, 0);
4509 R_Mesh_ResetTextureState();
4511 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4512 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4515 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4517 // transparent sky would be ridiculous
4518 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4520 if (rsurface.mode != RSURFMODE_SKY)
4522 if (rsurface.mode == RSURFMODE_GLSL)
4524 qglUseProgramObjectARB(0);CHECKGLERROR
4526 rsurface.mode = RSURFMODE_SKY;
4530 skyrendernow = false;
4532 // restore entity matrix
4533 R_Mesh_Matrix(&rsurface.matrix);
4535 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4536 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4537 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4538 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4540 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4541 // skymasking on them, and Quake3 never did sky masking (unlike
4542 // software Quake and software Quake2), so disable the sky masking
4543 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4544 // and skymasking also looks very bad when noclipping outside the
4545 // level, so don't use it then either.
4546 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4548 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4549 R_Mesh_ColorPointer(NULL, 0, 0);
4550 R_Mesh_ResetTextureState();
4551 if (skyrendermasked)
4553 // depth-only (masking)
4554 GL_ColorMask(0,0,0,0);
4555 // just to make sure that braindead drivers don't draw
4556 // anything despite that colormask...
4557 GL_BlendFunc(GL_ZERO, GL_ONE);
4562 GL_BlendFunc(GL_ONE, GL_ZERO);
4564 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4565 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4566 if (skyrendermasked)
4567 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4571 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4573 if (rsurface.mode != RSURFMODE_GLSL)
4575 rsurface.mode = RSURFMODE_GLSL;
4576 R_Mesh_ResetTextureState();
4579 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4580 if (!r_glsl_permutation)
4583 if (rsurface.lightmode == 2)
4584 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4586 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4587 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4588 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4589 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4590 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4591 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4593 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]);
4594 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4596 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4597 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4598 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4599 R_Mesh_ColorPointer(NULL, 0, 0);
4601 else if (rsurface.uselightmaptexture)
4603 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4604 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4605 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4606 R_Mesh_ColorPointer(NULL, 0, 0);
4610 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4611 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4612 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4613 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4616 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4617 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4619 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4620 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4625 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4627 // OpenGL 1.3 path - anything not completely ancient
4628 int texturesurfaceindex;
4629 qboolean applycolor;
4633 const texturelayer_t *layer;
4634 if (rsurface.mode != RSURFMODE_MULTIPASS)
4635 rsurface.mode = RSURFMODE_MULTIPASS;
4636 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4637 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4640 int layertexrgbscale;
4641 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4643 if (layerindex == 0)
4647 GL_AlphaTest(false);
4648 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4651 GL_DepthMask(layer->depthmask);
4652 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4653 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4655 layertexrgbscale = 4;
4656 VectorScale(layer->color, 0.25f, layercolor);
4658 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4660 layertexrgbscale = 2;
4661 VectorScale(layer->color, 0.5f, layercolor);
4665 layertexrgbscale = 1;
4666 VectorScale(layer->color, 1.0f, layercolor);
4668 layercolor[3] = layer->color[3];
4669 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4670 R_Mesh_ColorPointer(NULL, 0, 0);
4671 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4672 switch (layer->type)
4674 case TEXTURELAYERTYPE_LITTEXTURE:
4675 memset(&m, 0, sizeof(m));
4676 m.tex[0] = R_GetTexture(r_texture_white);
4677 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4678 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4679 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4680 m.tex[1] = R_GetTexture(layer->texture);
4681 m.texmatrix[1] = layer->texmatrix;
4682 m.texrgbscale[1] = layertexrgbscale;
4683 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4684 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4685 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4686 R_Mesh_TextureState(&m);
4687 if (rsurface.lightmode == 2)
4688 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4689 else if (rsurface.uselightmaptexture)
4690 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4692 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4694 case TEXTURELAYERTYPE_TEXTURE:
4695 memset(&m, 0, sizeof(m));
4696 m.tex[0] = R_GetTexture(layer->texture);
4697 m.texmatrix[0] = layer->texmatrix;
4698 m.texrgbscale[0] = layertexrgbscale;
4699 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4700 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4701 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4702 R_Mesh_TextureState(&m);
4703 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4705 case TEXTURELAYERTYPE_FOG:
4706 memset(&m, 0, sizeof(m));
4707 m.texrgbscale[0] = layertexrgbscale;
4710 m.tex[0] = R_GetTexture(layer->texture);
4711 m.texmatrix[0] = layer->texmatrix;
4712 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4713 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4714 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4716 R_Mesh_TextureState(&m);
4717 // generate a color array for the fog pass
4718 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4719 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4723 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4724 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)
4726 f = 1 - FogPoint_Model(v);
4727 c[0] = layercolor[0];
4728 c[1] = layercolor[1];
4729 c[2] = layercolor[2];
4730 c[3] = f * layercolor[3];
4733 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4736 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4738 GL_LockArrays(0, 0);
4741 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4743 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4744 GL_AlphaTest(false);
4748 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4750 // OpenGL 1.1 - crusty old voodoo path
4751 int texturesurfaceindex;
4755 const texturelayer_t *layer;
4756 if (rsurface.mode != RSURFMODE_MULTIPASS)
4757 rsurface.mode = RSURFMODE_MULTIPASS;
4758 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4759 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4761 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4763 if (layerindex == 0)
4767 GL_AlphaTest(false);
4768 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4771 GL_DepthMask(layer->depthmask);
4772 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4773 R_Mesh_ColorPointer(NULL, 0, 0);
4774 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4775 switch (layer->type)
4777 case TEXTURELAYERTYPE_LITTEXTURE:
4778 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4780 // two-pass lit texture with 2x rgbscale
4781 // first the lightmap pass
4782 memset(&m, 0, sizeof(m));
4783 m.tex[0] = R_GetTexture(r_texture_white);
4784 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4785 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4786 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4787 R_Mesh_TextureState(&m);
4788 if (rsurface.lightmode == 2)
4789 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4790 else if (rsurface.uselightmaptexture)
4791 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4793 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4794 GL_LockArrays(0, 0);
4795 // then apply the texture to it
4796 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4797 memset(&m, 0, sizeof(m));
4798 m.tex[0] = R_GetTexture(layer->texture);
4799 m.texmatrix[0] = layer->texmatrix;
4800 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4801 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4802 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4803 R_Mesh_TextureState(&m);
4804 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);
4808 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4809 memset(&m, 0, sizeof(m));
4810 m.tex[0] = R_GetTexture(layer->texture);
4811 m.texmatrix[0] = layer->texmatrix;
4812 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4813 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4814 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4815 R_Mesh_TextureState(&m);
4816 if (rsurface.lightmode == 2)
4817 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);
4819 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);
4822 case TEXTURELAYERTYPE_TEXTURE:
4823 // singletexture unlit texture with transparency support
4824 memset(&m, 0, sizeof(m));
4825 m.tex[0] = R_GetTexture(layer->texture);
4826 m.texmatrix[0] = layer->texmatrix;
4827 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4828 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4829 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4830 R_Mesh_TextureState(&m);
4831 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);
4833 case TEXTURELAYERTYPE_FOG:
4834 // singletexture fogging
4835 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4838 memset(&m, 0, sizeof(m));
4839 m.tex[0] = R_GetTexture(layer->texture);
4840 m.texmatrix[0] = layer->texmatrix;
4841 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4842 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4843 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4844 R_Mesh_TextureState(&m);
4847 R_Mesh_ResetTextureState();
4848 // generate a color array for the fog pass
4849 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4853 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4854 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)
4856 f = 1 - FogPoint_Model(v);
4857 c[0] = layer->color[0];
4858 c[1] = layer->color[1];
4859 c[2] = layer->color[2];
4860 c[3] = f * layer->color[3];
4863 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4866 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4868 GL_LockArrays(0, 0);
4871 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4873 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4874 GL_AlphaTest(false);
4878 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4880 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4882 rsurface.rtlight = NULL;
4886 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4888 if (rsurface.mode != RSURFMODE_MULTIPASS)
4889 rsurface.mode = RSURFMODE_MULTIPASS;
4890 if (r_depthfirst.integer == 3)
4892 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4893 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4897 GL_ColorMask(0,0,0,0);
4900 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4901 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4902 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4904 GL_BlendFunc(GL_ONE, GL_ZERO);
4906 GL_AlphaTest(false);
4907 R_Mesh_ColorPointer(NULL, 0, 0);
4908 R_Mesh_ResetTextureState();
4909 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4910 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4911 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4912 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4914 else if (r_depthfirst.integer == 3)
4916 else if (r_showsurfaces.integer)
4918 if (rsurface.mode != RSURFMODE_MULTIPASS)
4919 rsurface.mode = RSURFMODE_MULTIPASS;
4920 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4921 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4923 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4924 GL_BlendFunc(GL_ONE, GL_ZERO);
4925 GL_DepthMask(writedepth);
4927 GL_AlphaTest(false);
4928 R_Mesh_ColorPointer(NULL, 0, 0);
4929 R_Mesh_ResetTextureState();
4930 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4931 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4932 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4934 else if (gl_lightmaps.integer)
4937 if (rsurface.mode != RSURFMODE_MULTIPASS)
4938 rsurface.mode = RSURFMODE_MULTIPASS;
4939 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4941 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4942 GL_BlendFunc(GL_ONE, GL_ZERO);
4943 GL_DepthMask(writedepth);
4945 GL_AlphaTest(false);
4946 R_Mesh_ColorPointer(NULL, 0, 0);
4947 memset(&m, 0, sizeof(m));
4948 m.tex[0] = R_GetTexture(r_texture_white);
4949 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4950 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4951 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4952 R_Mesh_TextureState(&m);
4953 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
4954 if (rsurface.lightmode == 2)
4955 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4956 else if (rsurface.uselightmaptexture)
4957 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4959 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4960 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4962 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
4964 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4965 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4967 else if (rsurface.texture->currentnumlayers)
4969 // write depth for anything we skipped on the depth-only pass earlier
4970 if (!writedepth && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4972 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4973 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4974 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4975 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4976 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4977 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4978 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4979 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
4980 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
4981 if (r_glsl.integer && gl_support_fragment_shader)
4982 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4983 else if (gl_combine.integer && r_textureunits.integer >= 2)
4984 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4986 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4987 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4990 GL_LockArrays(0, 0);
4993 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4996 int texturenumsurfaces, endsurface;
4998 msurface_t *surface;
4999 msurface_t *texturesurfacelist[1024];
5001 // if the model is static it doesn't matter what value we give for
5002 // wantnormals and wanttangents, so this logic uses only rules applicable
5003 // to a model, knowing that they are meaningless otherwise
5004 if (ent == r_refdef.worldentity)
5005 RSurf_ActiveWorldEntity();
5006 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5007 RSurf_ActiveModelEntity(ent, false, false);
5009 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5011 for (i = 0;i < numsurfaces;i = j)
5014 surface = rsurface.modelsurfaces + surfacelist[i];
5015 texture = surface->texture;
5016 R_UpdateTextureInfo(ent, texture);
5017 rsurface.texture = texture->currentframe;
5018 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5019 // scan ahead until we find a different texture
5020 endsurface = min(i + 1024, numsurfaces);
5021 texturenumsurfaces = 0;
5022 texturesurfacelist[texturenumsurfaces++] = surface;
5023 for (;j < endsurface;j++)
5025 surface = rsurface.modelsurfaces + surfacelist[j];
5026 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5028 texturesurfacelist[texturenumsurfaces++] = surface;
5030 // render the range of surfaces
5031 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5037 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5040 vec3_t tempcenter, center;
5042 // break the surface list down into batches by texture and use of lightmapping
5043 for (i = 0;i < numsurfaces;i = j)
5046 // texture is the base texture pointer, rsurface.texture is the
5047 // current frame/skin the texture is directing us to use (for example
5048 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5049 // use skin 1 instead)
5050 texture = surfacelist[i]->texture;
5051 rsurface.texture = texture->currentframe;
5052 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5053 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5055 // if this texture is not the kind we want, skip ahead to the next one
5056 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5060 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5062 // transparent surfaces get pushed off into the transparent queue
5063 const msurface_t *surface = surfacelist[i];
5066 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5067 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5068 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5069 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5070 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5074 // simply scan ahead until we find a different texture or lightmap state
5075 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5077 // render the range of surfaces
5078 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5083 float locboxvertex3f[6*4*3] =
5085 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5086 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5087 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5088 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5089 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5090 1,0,0, 0,0,0, 0,1,0, 1,1,0
5093 int locboxelement3i[6*2*3] =
5103 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5106 cl_locnode_t *loc = (cl_locnode_t *)ent;
5108 float vertex3f[6*4*3];
5110 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5111 GL_DepthMask(false);
5112 GL_DepthRange(0, 1);
5113 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5115 GL_CullFace(GL_NONE);
5116 R_Mesh_Matrix(&identitymatrix);
5118 R_Mesh_VertexPointer(vertex3f, 0, 0);
5119 R_Mesh_ColorPointer(NULL, 0, 0);
5120 R_Mesh_ResetTextureState();
5123 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5124 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5125 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5126 surfacelist[0] < 0 ? 0.5f : 0.125f);
5128 if (VectorCompare(loc->mins, loc->maxs))
5130 VectorSet(size, 2, 2, 2);
5131 VectorMA(loc->mins, -0.5f, size, mins);
5135 VectorCopy(loc->mins, mins);
5136 VectorSubtract(loc->maxs, loc->mins, size);
5139 for (i = 0;i < 6*4*3;)
5140 for (j = 0;j < 3;j++, i++)
5141 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5143 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5146 void R_DrawLocs(void)
5149 cl_locnode_t *loc, *nearestloc;
5151 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5152 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5154 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5155 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5159 void R_DrawCollisionBrushes(entity_render_t *ent)
5163 msurface_t *surface;
5164 model_t *model = ent->model;
5165 if (!model->brush.num_brushes)
5168 R_Mesh_ColorPointer(NULL, 0, 0);
5169 R_Mesh_ResetTextureState();
5170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5171 GL_DepthMask(false);
5172 GL_DepthRange(0, 1);
5173 GL_DepthTest(!r_showdisabledepthtest.integer);
5174 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5175 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5176 if (brush->colbrushf && brush->colbrushf->numtriangles)
5177 R_DrawCollisionBrush(brush->colbrushf);
5178 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5179 if (surface->num_collisiontriangles)
5180 R_DrawCollisionSurface(ent, surface);
5181 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5184 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5187 const int *elements;
5188 msurface_t *surface;
5189 model_t *model = ent->model;
5192 GL_DepthRange(0, 1);
5193 GL_DepthTest(!r_showdisabledepthtest.integer);
5194 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5196 GL_BlendFunc(GL_ONE, GL_ZERO);
5197 R_Mesh_ColorPointer(NULL, 0, 0);
5198 R_Mesh_ResetTextureState();
5199 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5201 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5203 rsurface.texture = surface->texture->currentframe;
5204 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5206 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5209 if (!rsurface.texture->currentlayers->depthmask)
5210 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5211 else if (ent == r_refdef.worldentity)
5212 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5214 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5215 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5218 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5220 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5221 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5222 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5223 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5230 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5232 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5234 VectorCopy(rsurface.vertex3f + l * 3, v);
5235 qglVertex3f(v[0], v[1], v[2]);
5236 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5237 qglVertex3f(v[0], v[1], v[2]);
5241 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5243 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5245 VectorCopy(rsurface.vertex3f + l * 3, v);
5246 qglVertex3f(v[0], v[1], v[2]);
5247 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5248 qglVertex3f(v[0], v[1], v[2]);
5252 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5254 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5256 VectorCopy(rsurface.vertex3f + l * 3, v);
5257 qglVertex3f(v[0], v[1], v[2]);
5258 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5259 qglVertex3f(v[0], v[1], v[2]);
5266 rsurface.texture = NULL;
5269 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5270 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5272 int i, j, endj, f, flagsmask;
5273 int counttriangles = 0;
5274 msurface_t *surface, **surfacechain;
5276 model_t *model = r_refdef.worldmodel;
5277 const int maxsurfacelist = 1024;
5278 int numsurfacelist = 0;
5279 msurface_t *surfacelist[1024];
5283 RSurf_ActiveWorldEntity();
5285 // update light styles
5286 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5288 for (i = 0;i < model->brushq1.light_styles;i++)
5290 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5292 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5293 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5294 for (;(surface = *surfacechain);surfacechain++)
5295 surface->cached_dlight = true;
5300 R_UpdateAllTextureInfo(r_refdef.worldentity);
5301 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5304 rsurface.uselightmaptexture = false;
5305 rsurface.texture = NULL;
5307 j = model->firstmodelsurface;
5308 endj = j + model->nummodelsurfaces;
5311 // quickly skip over non-visible surfaces
5312 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5314 // quickly iterate over visible surfaces
5315 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5317 // process this surface
5318 surface = model->data_surfaces + j;
5319 // if this surface fits the criteria, add it to the list
5320 if (surface->num_triangles)
5322 // if lightmap parameters changed, rebuild lightmap texture
5323 if (surface->cached_dlight)
5324 R_BuildLightMap(r_refdef.worldentity, surface);
5325 // add face to draw list
5326 surfacelist[numsurfacelist++] = surface;
5327 counttriangles += surface->num_triangles;
5328 if (numsurfacelist >= maxsurfacelist)
5330 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5337 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5338 r_refdef.stats.entities_triangles += counttriangles;
5341 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5342 R_DrawCollisionBrushes(r_refdef.worldentity);
5344 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5345 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5348 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5350 int i, f, flagsmask;
5351 int counttriangles = 0;
5352 msurface_t *surface, *endsurface, **surfacechain;
5354 model_t *model = ent->model;
5355 const int maxsurfacelist = 1024;
5356 int numsurfacelist = 0;
5357 msurface_t *surfacelist[1024];
5361 // if the model is static it doesn't matter what value we give for
5362 // wantnormals and wanttangents, so this logic uses only rules applicable
5363 // to a model, knowing that they are meaningless otherwise
5364 if (ent == r_refdef.worldentity)
5365 RSurf_ActiveWorldEntity();
5366 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5367 RSurf_ActiveModelEntity(ent, false, false);
5369 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5371 // update light styles
5372 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5374 for (i = 0;i < model->brushq1.light_styles;i++)
5376 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5378 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5379 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5380 for (;(surface = *surfacechain);surfacechain++)
5381 surface->cached_dlight = true;
5386 R_UpdateAllTextureInfo(ent);
5387 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5390 rsurface.uselightmaptexture = false;
5391 rsurface.texture = NULL;
5393 surface = model->data_surfaces + model->firstmodelsurface;
5394 endsurface = surface + model->nummodelsurfaces;
5395 for (;surface < endsurface;surface++)
5397 // if this surface fits the criteria, add it to the list
5398 if (surface->num_triangles)
5400 // if lightmap parameters changed, rebuild lightmap texture
5401 if (surface->cached_dlight)
5402 R_BuildLightMap(ent, surface);
5403 // add face to draw list
5404 surfacelist[numsurfacelist++] = surface;
5405 counttriangles += surface->num_triangles;
5406 if (numsurfacelist >= maxsurfacelist)
5408 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5414 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5415 r_refdef.stats.entities_triangles += counttriangles;
5418 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5419 R_DrawCollisionBrushes(ent);
5421 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5422 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);