2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
85 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
86 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
88 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
89 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
90 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
91 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
92 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
93 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
94 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
96 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
97 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
98 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
99 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
101 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
103 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
105 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
107 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
108 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
110 extern qboolean v_flipped_state;
112 typedef struct r_glsl_bloomshader_s
115 int loc_Texture_Bloom;
117 r_glsl_bloomshader_t;
119 static struct r_bloomstate_s
124 int bloomwidth, bloomheight;
126 int screentexturewidth, screentextureheight;
127 rtexture_t *texture_screen;
129 int bloomtexturewidth, bloomtextureheight;
130 rtexture_t *texture_bloom;
132 r_glsl_bloomshader_t *shader;
134 // arrays for rendering the screen passes
135 float screentexcoord2f[8];
136 float bloomtexcoord2f[8];
137 float offsettexcoord2f[8];
141 // shadow volume bsp struct with automatically growing nodes buffer
144 rtexture_t *r_texture_blanknormalmap;
145 rtexture_t *r_texture_white;
146 rtexture_t *r_texture_black;
147 rtexture_t *r_texture_notexture;
148 rtexture_t *r_texture_whitecube;
149 rtexture_t *r_texture_normalizationcube;
150 rtexture_t *r_texture_fogattenuation;
151 //rtexture_t *r_texture_fogintensity;
153 // information about each possible shader permutation
154 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
155 // currently selected permutation
156 r_glsl_permutation_t *r_glsl_permutation;
158 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
159 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
161 // vertex coordinates for a quad that covers the screen exactly
162 const static float r_screenvertex3f[12] =
170 extern void R_DrawModelShadows(void);
172 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
175 for (i = 0;i < verts;i++)
186 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
189 for (i = 0;i < verts;i++)
199 // FIXME: move this to client?
202 if (gamemode == GAME_NEHAHRA)
204 Cvar_Set("gl_fogenable", "0");
205 Cvar_Set("gl_fogdensity", "0.2");
206 Cvar_Set("gl_fogred", "0.3");
207 Cvar_Set("gl_foggreen", "0.3");
208 Cvar_Set("gl_fogblue", "0.3");
210 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
213 float FogPoint_World(const vec3_t p)
215 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
216 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
219 float FogPoint_Model(const vec3_t p)
221 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
222 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
225 static void R_BuildBlankTextures(void)
227 unsigned char data[4];
228 data[0] = 128; // normal X
229 data[1] = 128; // normal Y
230 data[2] = 255; // normal Z
231 data[3] = 128; // height
232 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
237 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
242 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 static void R_BuildNoTexture(void)
248 unsigned char pix[16][16][4];
249 // this makes a light grey/dark grey checkerboard texture
250 for (y = 0;y < 16;y++)
252 for (x = 0;x < 16;x++)
254 if ((y < 8) ^ (x < 8))
270 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
273 static void R_BuildWhiteCube(void)
275 unsigned char data[6*1*1*4];
276 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
277 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
278 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
279 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
280 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
281 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
282 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
285 static void R_BuildNormalizationCube(void)
289 vec_t s, t, intensity;
291 unsigned char data[6][NORMSIZE][NORMSIZE][4];
292 for (side = 0;side < 6;side++)
294 for (y = 0;y < NORMSIZE;y++)
296 for (x = 0;x < NORMSIZE;x++)
298 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
299 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
334 intensity = 127.0f / sqrt(DotProduct(v, v));
335 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
336 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
337 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
338 data[side][y][x][3] = 255;
342 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
345 static void R_BuildFogTexture(void)
349 unsigned char data1[FOGWIDTH][4];
350 //unsigned char data2[FOGWIDTH][4];
351 for (x = 0;x < FOGWIDTH;x++)
353 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
358 //data2[x][0] = 255 - b;
359 //data2[x][1] = 255 - b;
360 //data2[x][2] = 255 - b;
363 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
364 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
367 static const char *builtinshaderstring =
368 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
369 "// written by Forest 'LordHavoc' Hale\n"
371 "// common definitions between vertex shader and fragment shader:\n"
373 "#ifdef __GLSL_CG_DATA_TYPES\n"
374 "#define myhalf half\n"
375 "#define myhvec2 hvec2\n"
376 "#define myhvec3 hvec3\n"
377 "#define myhvec4 hvec4\n"
379 "#define myhalf float\n"
380 "#define myhvec2 vec2\n"
381 "#define myhvec3 vec3\n"
382 "#define myhvec4 vec4\n"
385 "varying vec2 TexCoord;\n"
386 "varying vec2 TexCoordLightmap;\n"
388 "varying vec3 CubeVector;\n"
389 "varying vec3 LightVector;\n"
390 "varying vec3 EyeVector;\n"
392 "varying vec3 EyeVectorModelSpace;\n"
395 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
396 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
397 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
402 "// vertex shader specific:\n"
403 "#ifdef VERTEX_SHADER\n"
405 "uniform vec3 LightPosition;\n"
406 "uniform vec3 EyePosition;\n"
407 "uniform vec3 LightDir;\n"
409 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
413 " gl_FrontColor = gl_Color;\n"
414 " // copy the surface texcoord\n"
415 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
416 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
417 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
420 "#ifdef MODE_LIGHTSOURCE\n"
421 " // transform vertex position into light attenuation/cubemap space\n"
422 " // (-1 to +1 across the light box)\n"
423 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
425 " // transform unnormalized light direction into tangent space\n"
426 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
427 " // normalize it per pixel)\n"
428 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
429 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
430 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
431 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
434 "#ifdef MODE_LIGHTDIRECTION\n"
435 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
436 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
437 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
440 " // transform unnormalized eye direction into tangent space\n"
442 " vec3 EyeVectorModelSpace;\n"
444 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
445 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
446 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
447 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
449 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
450 " VectorS = gl_MultiTexCoord1.xyz;\n"
451 " VectorT = gl_MultiTexCoord2.xyz;\n"
452 " VectorR = gl_MultiTexCoord3.xyz;\n"
455 " // transform vertex to camera space, using ftransform to match non-VS\n"
457 " gl_Position = ftransform();\n"
460 "#endif // VERTEX_SHADER\n"
465 "// fragment shader specific:\n"
466 "#ifdef FRAGMENT_SHADER\n"
468 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
469 "uniform sampler2D Texture_Normal;\n"
470 "uniform sampler2D Texture_Color;\n"
471 "uniform sampler2D Texture_Gloss;\n"
472 "uniform samplerCube Texture_Cube;\n"
473 "uniform sampler2D Texture_Attenuation;\n"
474 "uniform sampler2D Texture_FogMask;\n"
475 "uniform sampler2D Texture_Pants;\n"
476 "uniform sampler2D Texture_Shirt;\n"
477 "uniform sampler2D Texture_Lightmap;\n"
478 "uniform sampler2D Texture_Deluxemap;\n"
479 "uniform sampler2D Texture_Glow;\n"
481 "uniform myhvec3 LightColor;\n"
482 "uniform myhvec3 AmbientColor;\n"
483 "uniform myhvec3 DiffuseColor;\n"
484 "uniform myhvec3 SpecularColor;\n"
485 "uniform myhvec3 Color_Pants;\n"
486 "uniform myhvec3 Color_Shirt;\n"
487 "uniform myhvec3 FogColor;\n"
489 "uniform myhalf GlowScale;\n"
490 "uniform myhalf SceneBrightness;\n"
491 "#ifdef USECONTRASTBOOST\n"
492 "uniform myhalf ContrastBoostCoeff;\n"
495 "uniform float OffsetMapping_Scale;\n"
496 "uniform float OffsetMapping_Bias;\n"
497 "uniform float FogRangeRecip;\n"
499 "uniform myhalf AmbientScale;\n"
500 "uniform myhalf DiffuseScale;\n"
501 "uniform myhalf SpecularScale;\n"
502 "uniform myhalf SpecularPower;\n"
504 "#ifdef USEOFFSETMAPPING\n"
505 "vec2 OffsetMapping(vec2 TexCoord)\n"
507 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
508 " // 14 sample relief mapping: linear search and then binary search\n"
509 " // this basically steps forward a small amount repeatedly until it finds\n"
510 " // itself inside solid, then jitters forward and back using decreasing\n"
511 " // amounts to find the impact\n"
512 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
513 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
514 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
515 " vec3 RT = vec3(TexCoord, 1);\n"
516 " OffsetVector *= 0.1;\n"
517 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
518 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
519 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
520 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
521 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
522 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
523 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
524 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
525 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
526 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
527 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
528 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
529 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
530 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
533 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
534 " // this basically moves forward the full distance, and then backs up based\n"
535 " // on height of samples\n"
536 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
537 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
538 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
539 " TexCoord += OffsetVector;\n"
540 " OffsetVector *= 0.333;\n"
541 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
542 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " return TexCoord;\n"
551 "#ifdef USEOFFSETMAPPING\n"
552 " // apply offsetmapping\n"
553 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
554 "#define TexCoord TexCoordOffset\n"
557 " // combine the diffuse textures (base, pants, shirt)\n"
558 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
559 "#ifdef USECOLORMAPPING\n"
560 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
566 "#ifdef MODE_LIGHTSOURCE\n"
569 " // calculate surface normal, light normal, and specular normal\n"
570 " // compute color intensity for the two textures (colormap and glossmap)\n"
571 " // scale by light color and attenuation as efficiently as possible\n"
572 " // (do as much scalar math as possible rather than vector math)\n"
573 "#ifdef USESPECULAR\n"
574 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
575 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
576 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
578 " // calculate directional shading\n"
579 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
581 "#ifdef USEDIFFUSE\n"
582 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
583 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
585 " // calculate directional shading\n"
586 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
588 " // calculate directionless shading\n"
589 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
593 "#ifdef USECUBEFILTER\n"
594 " // apply light cubemap filter\n"
595 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
596 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
602 "#elif defined(MODE_LIGHTDIRECTION)\n"
603 " // directional model lighting\n"
605 " // get the surface normal and light normal\n"
606 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
607 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
609 " // calculate directional shading\n"
610 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
611 "#ifdef USESPECULAR\n"
612 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
613 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
619 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
620 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
622 " // get the surface normal and light normal\n"
623 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
625 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
626 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
627 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
629 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
631 " // calculate directional shading\n"
632 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
633 "#ifdef USESPECULAR\n"
634 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
635 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
638 " // apply lightmap color\n"
639 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
642 "#else // MODE none (lightmap)\n"
643 " // apply lightmap color\n"
644 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
647 " color *= myhvec4(gl_Color);\n"
650 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
655 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
658 "#ifdef USECONTRASTBOOST\n"
659 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
661 " color.rgb *= SceneBrightness;\n"
664 " gl_FragColor = vec4(color);\n"
667 "#endif // FRAGMENT_SHADER\n"
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 const char *permutationinfo[][2] =
673 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
674 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
677 {"#define USEGLOW\n", " glow"},
678 {"#define USEFOG\n", " fog"},
679 {"#define USECOLORMAPPING\n", " colormapping"},
680 {"#define USEDIFFUSE\n", " diffuse"},
681 {"#define USECONTRASTBOOST\n", " contrastboost"},
682 {"#define USESPECULAR\n", " specular"},
683 {"#define USECUBEFILTER\n", " cubefilter"},
684 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
685 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
689 void R_GLSL_CompilePermutation(const char *filename, int permutation)
692 qboolean shaderfound;
693 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
694 int vertstrings_count;
695 int geomstrings_count;
696 int fragstrings_count;
698 const char *vertstrings_list[32+1];
699 const char *geomstrings_list[32+1];
700 const char *fragstrings_list[32+1];
701 char permutationname[256];
706 vertstrings_list[0] = "#define VERTEX_SHADER\n";
707 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
708 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
709 vertstrings_count = 1;
710 geomstrings_count = 1;
711 fragstrings_count = 1;
712 permutationname[0] = 0;
713 for (i = 0;permutationinfo[i][0];i++)
715 if (permutation & (1<<i))
717 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
718 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
719 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
720 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
724 // keep line numbers correct
725 vertstrings_list[vertstrings_count++] = "\n";
726 geomstrings_list[geomstrings_count++] = "\n";
727 fragstrings_list[fragstrings_count++] = "\n";
730 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
734 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
735 vertstrings_list[vertstrings_count++] = shaderstring;
736 geomstrings_list[geomstrings_count++] = shaderstring;
737 fragstrings_list[fragstrings_count++] = shaderstring;
740 else if (!strcmp(filename, "glsl/default.glsl"))
742 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
743 vertstrings_list[vertstrings_count++] = builtinshaderstring;
744 geomstrings_list[geomstrings_count++] = builtinshaderstring;
745 fragstrings_list[fragstrings_count++] = builtinshaderstring;
748 // clear any lists that are not needed by this shader
749 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
750 vertstrings_count = 0;
751 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
752 geomstrings_count = 0;
753 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
754 fragstrings_count = 0;
755 // compile the shader program
756 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
757 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
761 qglUseProgramObjectARB(p->program);CHECKGLERROR
762 // look up all the uniform variable names we care about, so we don't
763 // have to look them up every time we set them
764 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
765 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
766 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
767 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
768 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
769 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
770 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
771 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
772 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
773 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
774 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
775 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
776 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
777 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
778 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
779 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
780 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
781 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
782 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
783 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
784 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
785 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
786 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
787 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
788 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
789 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
790 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
791 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
792 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
793 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
794 // initialize the samplers to refer to the texture units we use
795 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
796 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
797 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
798 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
799 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
800 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
801 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
802 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
803 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
804 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
805 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
807 qglUseProgramObjectARB(0);CHECKGLERROR
810 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
812 Mem_Free(shaderstring);
815 void R_GLSL_Restart_f(void)
818 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
819 if (r_glsl_permutations[i].program)
820 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
821 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
824 void R_GLSL_DumpShader_f(void)
828 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
831 Con_Printf("failed to write to glsl/default.glsl\n");
835 FS_Print(file, "// #define VERTEX_SHADER GEOMETRY_SHADER FRAGMENT_SHADER\n");
836 for (i = 0;permutationinfo[i][0];i++)
837 FS_Printf(file, "// %s", permutationinfo[i][0]);
838 FS_Print(file, "\n");
839 FS_Print(file, builtinshaderstring);
842 Con_Printf("data/default.glsl written");
845 extern rtexture_t *r_shadow_attenuationgradienttexture;
846 extern rtexture_t *r_shadow_attenuation2dtexture;
847 extern rtexture_t *r_shadow_attenuation3dtexture;
848 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
854 const char *shaderfilename = NULL;
855 unsigned int permutation = 0;
856 r_glsl_permutation = NULL;
857 // TODO: implement geometry-shader based shadow volumes someday
858 if (rsurface.rtlight)
861 shaderfilename = "glsl/default.glsl";
862 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
863 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
864 permutation |= SHADERPERMUTATION_CUBEFILTER;
865 if (diffusescale > 0)
866 permutation |= SHADERPERMUTATION_DIFFUSE;
867 if (specularscale > 0)
868 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
869 if (r_refdef.fogenabled)
870 permutation |= SHADERPERMUTATION_FOG;
871 if (rsurface.texture->colormapping)
872 permutation |= SHADERPERMUTATION_COLORMAPPING;
873 if (r_glsl_offsetmapping.integer)
875 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
876 if (r_glsl_offsetmapping_reliefmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
879 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
880 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
882 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
884 // bright unshaded geometry
885 shaderfilename = "glsl/default.glsl";
886 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
887 if (rsurface.texture->currentskinframe->glow)
888 permutation |= SHADERPERMUTATION_GLOW;
889 if (r_refdef.fogenabled)
890 permutation |= SHADERPERMUTATION_FOG;
891 if (rsurface.texture->colormapping)
892 permutation |= SHADERPERMUTATION_COLORMAPPING;
893 if (r_glsl_offsetmapping.integer)
895 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
896 if (r_glsl_offsetmapping_reliefmapping.integer)
897 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
899 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
900 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
902 else if (modellighting)
904 // directional model lighting
905 shaderfilename = "glsl/default.glsl";
906 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
907 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
908 if (rsurface.texture->currentskinframe->glow)
909 permutation |= SHADERPERMUTATION_GLOW;
910 if (specularscale > 0)
911 permutation |= SHADERPERMUTATION_SPECULAR;
912 if (r_refdef.fogenabled)
913 permutation |= SHADERPERMUTATION_FOG;
914 if (rsurface.texture->colormapping)
915 permutation |= SHADERPERMUTATION_COLORMAPPING;
916 if (r_glsl_offsetmapping.integer)
918 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
919 if (r_glsl_offsetmapping_reliefmapping.integer)
920 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
922 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
923 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
928 shaderfilename = "glsl/default.glsl";
929 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
930 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
932 // deluxemapping (light direction texture)
933 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
934 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
936 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
937 if (specularscale > 0)
938 permutation |= SHADERPERMUTATION_SPECULAR;
940 else if (r_glsl_deluxemapping.integer >= 2)
942 // fake deluxemapping (uniform light direction in tangentspace)
943 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
944 if (specularscale > 0)
945 permutation |= SHADERPERMUTATION_SPECULAR;
949 // ordinary lightmapping
952 if (rsurface.texture->currentskinframe->glow)
953 permutation |= SHADERPERMUTATION_GLOW;
954 if (r_refdef.fogenabled)
955 permutation |= SHADERPERMUTATION_FOG;
956 if (rsurface.texture->colormapping)
957 permutation |= SHADERPERMUTATION_COLORMAPPING;
958 if (r_glsl_offsetmapping.integer)
960 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
961 if (r_glsl_offsetmapping_reliefmapping.integer)
962 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
964 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
965 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
967 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
969 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
970 R_GLSL_CompilePermutation(shaderfilename, permutation);
971 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
973 // remove features until we find a valid permutation
975 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
978 return 0; // no bit left to clear
979 // reduce i more quickly whenever it would not remove any bits
980 if (!(permutation & i))
983 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
984 R_GLSL_CompilePermutation(shaderfilename, permutation);
985 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
990 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
992 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
993 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
994 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
996 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
997 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
998 if (permutation & SHADERPERMUTATION_DIFFUSE)
1000 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1001 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1002 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1003 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1007 // ambient only is simpler
1008 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1009 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1010 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1011 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1014 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1016 if (r_glsl_permutation->loc_AmbientColor >= 0)
1017 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1018 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1019 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1020 if (r_glsl_permutation->loc_SpecularColor >= 0)
1021 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1022 if (r_glsl_permutation->loc_LightDir >= 0)
1023 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1027 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1028 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1029 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1031 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
1032 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1033 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1034 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1035 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1036 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1037 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1038 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1039 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1040 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1041 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1042 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1043 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1045 // The formula used is actually:
1046 // color.rgb *= SceneBrightness;
1047 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1048 // I simplify that to
1049 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1050 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1052 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1053 // and do [[calculations]] here in the engine
1054 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1055 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1058 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1059 if (r_glsl_permutation->loc_FogColor >= 0)
1061 // additive passes are only darkened by fog, not tinted
1062 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1063 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1065 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1067 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1068 if (r_glsl_permutation->loc_Color_Pants >= 0)
1070 if (rsurface.texture->currentskinframe->pants)
1071 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1073 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1075 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1077 if (rsurface.texture->currentskinframe->shirt)
1078 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1080 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1082 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1083 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1084 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1089 void R_SwitchSurfaceShader(int permutation)
1091 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1093 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1095 qglUseProgramObjectARB(r_glsl_permutation->program);
1100 #define SKINFRAME_HASH 1024
1104 int loadsequence; // incremented each level change
1105 memexpandablearray_t array;
1106 skinframe_t *hash[SKINFRAME_HASH];
1110 void R_SkinFrame_PrepareForPurge(void)
1112 r_skinframe.loadsequence++;
1113 // wrap it without hitting zero
1114 if (r_skinframe.loadsequence >= 200)
1115 r_skinframe.loadsequence = 1;
1118 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1122 // mark the skinframe as used for the purging code
1123 skinframe->loadsequence = r_skinframe.loadsequence;
1126 void R_SkinFrame_Purge(void)
1130 for (i = 0;i < SKINFRAME_HASH;i++)
1132 for (s = r_skinframe.hash[i];s;s = s->next)
1134 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1136 if (s->base == r_texture_notexture) s->base = NULL;
1137 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1138 if (s->merged == s->base) s->merged = NULL;
1139 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1140 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1141 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1142 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1143 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1144 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1145 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1146 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1147 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1148 s->loadsequence = 0;
1154 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1158 char basename[MAX_QPATH];
1160 Image_StripImageExtension(name, basename, sizeof(basename));
1162 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1163 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1164 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1170 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1171 memset(item, 0, sizeof(*item));
1172 strlcpy(item->basename, basename, sizeof(item->basename));
1173 item->textureflags = textureflags;
1174 item->comparewidth = comparewidth;
1175 item->compareheight = compareheight;
1176 item->comparecrc = comparecrc;
1177 item->next = r_skinframe.hash[hashindex];
1178 r_skinframe.hash[hashindex] = item;
1180 R_SkinFrame_MarkUsed(item);
1184 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1186 // FIXME: it should be possible to disable loading various layers using
1187 // cvars, to prevent wasted loading time and memory usage if the user does
1189 qboolean loadnormalmap = true;
1190 qboolean loadgloss = true;
1191 qboolean loadpantsandshirt = true;
1192 qboolean loadglow = true;
1194 unsigned char *pixels;
1195 unsigned char *bumppixels;
1196 unsigned char *basepixels = NULL;
1197 int basepixels_width;
1198 int basepixels_height;
1199 skinframe_t *skinframe;
1201 if (cls.state == ca_dedicated)
1204 // return an existing skinframe if already loaded
1205 // if loading of the first image fails, don't make a new skinframe as it
1206 // would cause all future lookups of this to be missing
1207 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1208 if (skinframe && skinframe->base)
1211 basepixels = loadimagepixels(name, complain, 0, 0);
1212 if (basepixels == NULL)
1215 // we've got some pixels to store, so really allocate this new texture now
1217 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1218 skinframe->stain = NULL;
1219 skinframe->merged = NULL;
1220 skinframe->base = r_texture_notexture;
1221 skinframe->pants = NULL;
1222 skinframe->shirt = NULL;
1223 skinframe->nmap = r_texture_blanknormalmap;
1224 skinframe->gloss = NULL;
1225 skinframe->glow = NULL;
1226 skinframe->fog = NULL;
1228 basepixels_width = image_width;
1229 basepixels_height = image_height;
1230 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1232 if (textureflags & TEXF_ALPHA)
1234 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1235 if (basepixels[j] < 255)
1237 if (j < basepixels_width * basepixels_height * 4)
1239 // has transparent pixels
1240 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1241 for (j = 0;j < image_width * image_height * 4;j += 4)
1246 pixels[j+3] = basepixels[j+3];
1248 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1253 // _norm is the name used by tenebrae and has been adopted as standard
1256 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1258 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1262 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1264 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1265 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1266 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1268 Mem_Free(bumppixels);
1270 else if (r_shadow_bumpscale_basetexture.value > 0)
1272 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1273 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1274 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1278 // _luma is supported for tenebrae compatibility
1279 // (I think it's a very stupid name, but oh well)
1280 // _glow is the preferred name
1281 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;}
1282 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;}
1283 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;}
1284 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;}
1287 Mem_Free(basepixels);
1292 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)
1297 for (i = 0;i < width*height;i++)
1298 if (((unsigned char *)&palette[in[i]])[3] > 0)
1300 if (i == width*height)
1303 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1306 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)
1309 unsigned char *temp1, *temp2;
1310 skinframe_t *skinframe;
1312 if (cls.state == ca_dedicated)
1315 // if already loaded just return it, otherwise make a new skinframe
1316 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1317 if (skinframe && skinframe->base)
1320 skinframe->stain = NULL;
1321 skinframe->merged = NULL;
1322 skinframe->base = r_texture_notexture;
1323 skinframe->pants = NULL;
1324 skinframe->shirt = NULL;
1325 skinframe->nmap = r_texture_blanknormalmap;
1326 skinframe->gloss = NULL;
1327 skinframe->glow = NULL;
1328 skinframe->fog = NULL;
1330 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1334 if (bitsperpixel == 32)
1336 if (r_shadow_bumpscale_basetexture.value > 0)
1338 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1339 temp2 = temp1 + width * height * 4;
1340 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1341 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1344 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1345 if (textureflags & TEXF_ALPHA)
1347 for (i = 3;i < width * height * 4;i += 4)
1348 if (skindata[i] < 255)
1350 if (i < width * height * 4)
1352 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1353 memcpy(fogpixels, skindata, width * height * 4);
1354 for (i = 0;i < width * height * 4;i += 4)
1355 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1356 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1357 Mem_Free(fogpixels);
1361 else if (bitsperpixel == 8)
1363 if (r_shadow_bumpscale_basetexture.value > 0)
1365 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1366 temp2 = temp1 + width * height * 4;
1367 if (bitsperpixel == 32)
1368 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1371 // use either a custom palette or the quake palette
1372 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1373 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1375 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1378 // use either a custom palette, or the quake palette
1379 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
1380 if (!palette && loadglowtexture)
1381 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1382 if (!palette && loadpantsandshirt)
1384 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1385 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1387 if (skinframe->pants || skinframe->shirt)
1388 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1389 if (textureflags & TEXF_ALPHA)
1391 // if not using a custom alphapalette, use the quake one
1393 alphapalette = palette_alpha;
1394 for (i = 0;i < width * height;i++)
1395 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1397 if (i < width * height)
1398 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1405 skinframe_t *R_SkinFrame_LoadMissing(void)
1407 skinframe_t *skinframe;
1409 if (cls.state == ca_dedicated)
1412 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1413 skinframe->stain = NULL;
1414 skinframe->merged = NULL;
1415 skinframe->base = r_texture_notexture;
1416 skinframe->pants = NULL;
1417 skinframe->shirt = NULL;
1418 skinframe->nmap = r_texture_blanknormalmap;
1419 skinframe->gloss = NULL;
1420 skinframe->glow = NULL;
1421 skinframe->fog = NULL;
1426 void gl_main_start(void)
1431 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1432 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1434 alpha = 1 - exp(r / ((double)x*(double)x));
1435 if (x == FOGMASKTABLEWIDTH - 1)
1437 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1440 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1441 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1443 // set up r_skinframe loading system for textures
1444 memset(&r_skinframe, 0, sizeof(r_skinframe));
1445 r_skinframe.loadsequence = 1;
1446 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1448 r_main_texturepool = R_AllocTexturePool();
1449 R_BuildBlankTextures();
1451 if (gl_texturecubemap)
1454 R_BuildNormalizationCube();
1456 R_BuildFogTexture();
1457 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1458 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1459 memset(&r_svbsp, 0, sizeof (r_svbsp));
1462 void gl_main_shutdown(void)
1464 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1465 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1467 // clear out the r_skinframe state
1468 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1469 memset(&r_skinframe, 0, sizeof(r_skinframe));
1472 Mem_Free(r_svbsp.nodes);
1473 memset(&r_svbsp, 0, sizeof (r_svbsp));
1474 R_FreeTexturePool(&r_main_texturepool);
1475 r_texture_blanknormalmap = NULL;
1476 r_texture_white = NULL;
1477 r_texture_black = NULL;
1478 r_texture_whitecube = NULL;
1479 r_texture_normalizationcube = NULL;
1480 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1484 extern void CL_ParseEntityLump(char *entitystring);
1485 void gl_main_newmap(void)
1487 // FIXME: move this code to client
1489 char *entities, entname[MAX_QPATH];
1492 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1493 l = (int)strlen(entname) - 4;
1494 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1496 memcpy(entname + l, ".ent", 5);
1497 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1499 CL_ParseEntityLump(entities);
1504 if (cl.worldmodel->brush.entities)
1505 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1509 void GL_Main_Init(void)
1511 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1513 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1514 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1515 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1516 if (gamemode == GAME_NEHAHRA)
1518 Cvar_RegisterVariable (&gl_fogenable);
1519 Cvar_RegisterVariable (&gl_fogdensity);
1520 Cvar_RegisterVariable (&gl_fogred);
1521 Cvar_RegisterVariable (&gl_foggreen);
1522 Cvar_RegisterVariable (&gl_fogblue);
1523 Cvar_RegisterVariable (&gl_fogstart);
1524 Cvar_RegisterVariable (&gl_fogend);
1526 Cvar_RegisterVariable(&r_depthfirst);
1527 Cvar_RegisterVariable(&r_nearclip);
1528 Cvar_RegisterVariable(&r_showbboxes);
1529 Cvar_RegisterVariable(&r_showsurfaces);
1530 Cvar_RegisterVariable(&r_showtris);
1531 Cvar_RegisterVariable(&r_shownormals);
1532 Cvar_RegisterVariable(&r_showlighting);
1533 Cvar_RegisterVariable(&r_showshadowvolumes);
1534 Cvar_RegisterVariable(&r_showcollisionbrushes);
1535 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1536 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1537 Cvar_RegisterVariable(&r_showdisabledepthtest);
1538 Cvar_RegisterVariable(&r_drawportals);
1539 Cvar_RegisterVariable(&r_drawentities);
1540 Cvar_RegisterVariable(&r_cullentities_trace);
1541 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1542 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1543 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1544 Cvar_RegisterVariable(&r_drawviewmodel);
1545 Cvar_RegisterVariable(&r_speeds);
1546 Cvar_RegisterVariable(&r_fullbrights);
1547 Cvar_RegisterVariable(&r_wateralpha);
1548 Cvar_RegisterVariable(&r_dynamic);
1549 Cvar_RegisterVariable(&r_fullbright);
1550 Cvar_RegisterVariable(&r_shadows);
1551 Cvar_RegisterVariable(&r_shadows_throwdistance);
1552 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1553 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1554 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1555 Cvar_RegisterVariable(&r_textureunits);
1556 Cvar_RegisterVariable(&r_glsl);
1557 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1558 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1559 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1560 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1561 Cvar_RegisterVariable(&r_lerpsprites);
1562 Cvar_RegisterVariable(&r_lerpmodels);
1563 Cvar_RegisterVariable(&r_waterscroll);
1564 Cvar_RegisterVariable(&r_bloom);
1565 Cvar_RegisterVariable(&r_bloom_colorscale);
1566 Cvar_RegisterVariable(&r_bloom_brighten);
1567 Cvar_RegisterVariable(&r_bloom_blur);
1568 Cvar_RegisterVariable(&r_bloom_resolution);
1569 Cvar_RegisterVariable(&r_bloom_colorexponent);
1570 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1571 Cvar_RegisterVariable(&r_hdr);
1572 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1573 Cvar_RegisterVariable(&r_glsl_contrastboost);
1574 Cvar_RegisterVariable(&r_hdr_glowintensity);
1575 Cvar_RegisterVariable(&r_hdr_range);
1576 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1577 Cvar_RegisterVariable(&developer_texturelogging);
1578 Cvar_RegisterVariable(&gl_lightmaps);
1579 Cvar_RegisterVariable(&r_test);
1580 Cvar_RegisterVariable(&r_batchmode);
1581 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1582 Cvar_SetValue("r_fullbrights", 0);
1583 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1586 extern void R_Textures_Init(void);
1587 extern void GL_Draw_Init(void);
1588 extern void GL_Main_Init(void);
1589 extern void R_Shadow_Init(void);
1590 extern void R_Sky_Init(void);
1591 extern void GL_Surf_Init(void);
1592 extern void R_Light_Init(void);
1593 extern void R_Particles_Init(void);
1594 extern void R_Explosion_Init(void);
1595 extern void gl_backend_init(void);
1596 extern void Sbar_Init(void);
1597 extern void R_LightningBeams_Init(void);
1598 extern void Mod_RenderInit(void);
1600 void Render_Init(void)
1613 R_LightningBeams_Init();
1622 extern char *ENGINE_EXTENSIONS;
1625 VID_CheckExtensions();
1627 // LordHavoc: report supported extensions
1628 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1630 // clear to black (loading plaque will be seen over this)
1632 qglClearColor(0,0,0,1);CHECKGLERROR
1633 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1636 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1640 for (i = 0;i < 4;i++)
1642 p = r_view.frustum + i;
1647 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1651 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1655 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1659 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1663 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1667 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1671 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1675 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1683 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1687 for (i = 0;i < numplanes;i++)
1694 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1698 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1702 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1706 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1710 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1714 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1718 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1722 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1730 //==================================================================================
1732 static void R_UpdateEntityLighting(entity_render_t *ent)
1734 vec3_t tempdiffusenormal;
1736 // fetch the lighting from the worldmodel data
1737 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));
1738 VectorClear(ent->modellight_diffuse);
1739 VectorClear(tempdiffusenormal);
1740 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1743 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1744 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1747 VectorSet(ent->modellight_ambient, 1, 1, 1);
1749 // move the light direction into modelspace coordinates for lighting code
1750 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1751 if(VectorLength2(ent->modellight_lightdir) > 0)
1753 VectorNormalize(ent->modellight_lightdir);
1757 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1760 // scale ambient and directional light contributions according to rendering variables
1761 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1762 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1763 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1764 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1765 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1766 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1769 static void R_View_UpdateEntityVisible (void)
1772 entity_render_t *ent;
1774 if (!r_drawentities.integer)
1777 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1778 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1780 // worldmodel can check visibility
1781 for (i = 0;i < r_refdef.numentities;i++)
1783 ent = r_refdef.entities[i];
1784 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));
1786 if(r_cullentities_trace.integer)
1788 for (i = 0;i < r_refdef.numentities;i++)
1790 ent = r_refdef.entities[i];
1791 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1793 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1794 ent->last_trace_visibility = realtime;
1795 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1796 r_viewcache.entityvisible[i] = 0;
1803 // no worldmodel or it can't check visibility
1804 for (i = 0;i < r_refdef.numentities;i++)
1806 ent = r_refdef.entities[i];
1807 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1811 // update entity lighting (even on hidden entities for r_shadows)
1812 for (i = 0;i < r_refdef.numentities;i++)
1813 R_UpdateEntityLighting(r_refdef.entities[i]);
1816 // only used if skyrendermasked, and normally returns false
1817 int R_DrawBrushModelsSky (void)
1820 entity_render_t *ent;
1822 if (!r_drawentities.integer)
1826 for (i = 0;i < r_refdef.numentities;i++)
1828 if (!r_viewcache.entityvisible[i])
1830 ent = r_refdef.entities[i];
1831 if (!ent->model || !ent->model->DrawSky)
1833 ent->model->DrawSky(ent);
1839 void R_DrawNoModel(entity_render_t *ent);
1840 void R_DrawModels(void)
1843 entity_render_t *ent;
1845 if (!r_drawentities.integer)
1848 for (i = 0;i < r_refdef.numentities;i++)
1850 if (!r_viewcache.entityvisible[i])
1852 ent = r_refdef.entities[i];
1853 r_refdef.stats.entities++;
1854 if (ent->model && ent->model->Draw != NULL)
1855 ent->model->Draw(ent);
1861 void R_DrawModelsDepth(void)
1864 entity_render_t *ent;
1866 if (!r_drawentities.integer)
1869 for (i = 0;i < r_refdef.numentities;i++)
1871 if (!r_viewcache.entityvisible[i])
1873 ent = r_refdef.entities[i];
1874 r_refdef.stats.entities++;
1875 if (ent->model && ent->model->DrawDepth != NULL)
1876 ent->model->DrawDepth(ent);
1880 static void R_View_SetFrustum(void)
1882 double slopex, slopey;
1884 // break apart the view matrix into vectors for various purposes
1885 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1886 VectorNegate(r_view.left, r_view.right);
1889 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1890 r_view.frustum[0].normal[1] = 0 - 0;
1891 r_view.frustum[0].normal[2] = -1 - 0;
1892 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1893 r_view.frustum[1].normal[1] = 0 + 0;
1894 r_view.frustum[1].normal[2] = -1 + 0;
1895 r_view.frustum[2].normal[0] = 0 - 0;
1896 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1897 r_view.frustum[2].normal[2] = -1 - 0;
1898 r_view.frustum[3].normal[0] = 0 + 0;
1899 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1900 r_view.frustum[3].normal[2] = -1 + 0;
1904 zNear = r_refdef.nearclip;
1905 nudge = 1.0 - 1.0 / (1<<23);
1906 r_view.frustum[4].normal[0] = 0 - 0;
1907 r_view.frustum[4].normal[1] = 0 - 0;
1908 r_view.frustum[4].normal[2] = -1 - -nudge;
1909 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1910 r_view.frustum[5].normal[0] = 0 + 0;
1911 r_view.frustum[5].normal[1] = 0 + 0;
1912 r_view.frustum[5].normal[2] = -1 + -nudge;
1913 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1919 r_view.frustum[0].normal[0] = m[3] - m[0];
1920 r_view.frustum[0].normal[1] = m[7] - m[4];
1921 r_view.frustum[0].normal[2] = m[11] - m[8];
1922 r_view.frustum[0].dist = m[15] - m[12];
1924 r_view.frustum[1].normal[0] = m[3] + m[0];
1925 r_view.frustum[1].normal[1] = m[7] + m[4];
1926 r_view.frustum[1].normal[2] = m[11] + m[8];
1927 r_view.frustum[1].dist = m[15] + m[12];
1929 r_view.frustum[2].normal[0] = m[3] - m[1];
1930 r_view.frustum[2].normal[1] = m[7] - m[5];
1931 r_view.frustum[2].normal[2] = m[11] - m[9];
1932 r_view.frustum[2].dist = m[15] - m[13];
1934 r_view.frustum[3].normal[0] = m[3] + m[1];
1935 r_view.frustum[3].normal[1] = m[7] + m[5];
1936 r_view.frustum[3].normal[2] = m[11] + m[9];
1937 r_view.frustum[3].dist = m[15] + m[13];
1939 r_view.frustum[4].normal[0] = m[3] - m[2];
1940 r_view.frustum[4].normal[1] = m[7] - m[6];
1941 r_view.frustum[4].normal[2] = m[11] - m[10];
1942 r_view.frustum[4].dist = m[15] - m[14];
1944 r_view.frustum[5].normal[0] = m[3] + m[2];
1945 r_view.frustum[5].normal[1] = m[7] + m[6];
1946 r_view.frustum[5].normal[2] = m[11] + m[10];
1947 r_view.frustum[5].dist = m[15] + m[14];
1952 if (r_view.useperspective)
1954 slopex = 1.0 / r_view.frustum_x;
1955 slopey = 1.0 / r_view.frustum_y;
1956 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1957 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1958 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1959 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1960 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1962 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1963 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1964 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1965 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1966 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1968 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1969 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1970 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1971 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1972 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1976 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1977 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
1978 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1979 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
1980 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1981 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1982 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1983 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
1984 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
1985 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1988 PlaneClassify(&r_view.frustum[0]);
1989 PlaneClassify(&r_view.frustum[1]);
1990 PlaneClassify(&r_view.frustum[2]);
1991 PlaneClassify(&r_view.frustum[3]);
1992 PlaneClassify(&r_view.frustum[4]);
1994 // LordHavoc: note to all quake engine coders, Quake had a special case
1995 // for 90 degrees which assumed a square view (wrong), so I removed it,
1996 // Quake2 has it disabled as well.
1998 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1999 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2000 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2001 //PlaneClassify(&frustum[0]);
2003 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2004 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2005 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2006 //PlaneClassify(&frustum[1]);
2008 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2009 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2010 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2011 //PlaneClassify(&frustum[2]);
2013 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2014 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2015 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2016 //PlaneClassify(&frustum[3]);
2019 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2020 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2021 //PlaneClassify(&frustum[4]);
2024 void R_View_Update(void)
2026 R_View_SetFrustum();
2027 R_View_WorldVisibility();
2028 R_View_UpdateEntityVisible();
2031 void R_SetupView(const matrix4x4_t *matrix)
2033 if (!r_view.useperspective)
2034 GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2035 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2036 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2038 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2040 GL_SetupView_Orientation_FromEntity(matrix);
2043 void R_ResetViewRendering2D(void)
2045 if (gl_support_fragment_shader)
2047 qglUseProgramObjectARB(0);CHECKGLERROR
2052 // GL is weird because it's bottom to top, r_view.y is top to bottom
2053 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2054 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2055 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2056 GL_Color(1, 1, 1, 1);
2057 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2058 GL_BlendFunc(GL_ONE, GL_ZERO);
2059 GL_AlphaTest(false);
2060 GL_ScissorTest(false);
2061 GL_DepthMask(false);
2062 GL_DepthRange(0, 1);
2063 GL_DepthTest(false);
2064 R_Mesh_Matrix(&identitymatrix);
2065 R_Mesh_ResetTextureState();
2066 GL_PolygonOffset(0, 0);
2067 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2068 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2069 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2070 qglStencilMask(~0);CHECKGLERROR
2071 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2072 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2073 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2076 void R_ResetViewRendering3D(void)
2078 if (gl_support_fragment_shader)
2080 qglUseProgramObjectARB(0);CHECKGLERROR
2085 // GL is weird because it's bottom to top, r_view.y is top to bottom
2086 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2087 R_SetupView(&r_view.matrix);
2088 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2089 GL_Color(1, 1, 1, 1);
2090 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2091 GL_BlendFunc(GL_ONE, GL_ZERO);
2092 GL_AlphaTest(false);
2093 GL_ScissorTest(true);
2095 GL_DepthRange(0, 1);
2097 R_Mesh_Matrix(&identitymatrix);
2098 R_Mesh_ResetTextureState();
2099 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2100 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2101 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2102 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2103 qglStencilMask(~0);CHECKGLERROR
2104 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2105 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2106 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2110 R_Bloom_SetupShader(
2112 "// written by Forest 'LordHavoc' Hale\n"
2114 "// common definitions between vertex shader and fragment shader:\n"
2116 "#ifdef __GLSL_CG_DATA_TYPES\n"
2117 "#define myhalf half\n"
2118 "#define myhvec2 hvec2\n"
2119 "#define myhvec3 hvec3\n"
2120 "#define myhvec4 hvec4\n"
2122 "#define myhalf float\n"
2123 "#define myhvec2 vec2\n"
2124 "#define myhvec3 vec3\n"
2125 "#define myhvec4 vec4\n"
2128 "varying vec2 ScreenTexCoord;\n"
2129 "varying vec2 BloomTexCoord;\n"
2134 "// vertex shader specific:\n"
2135 "#ifdef VERTEX_SHADER\n"
2139 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2140 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2141 " // transform vertex to camera space, using ftransform to match non-VS\n"
2143 " gl_Position = ftransform();\n"
2146 "#endif // VERTEX_SHADER\n"
2151 "// fragment shader specific:\n"
2152 "#ifdef FRAGMENT_SHADER\n"
2157 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2158 " for (x = -BLUR_X;x <= BLUR_X;x++)
2159 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2160 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2161 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2162 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2164 " gl_FragColor = vec4(color);\n"
2167 "#endif // FRAGMENT_SHADER\n"
2170 void R_RenderScene(void);
2172 void R_Bloom_StartFrame(void)
2174 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2176 // set bloomwidth and bloomheight to the bloom resolution that will be
2177 // used (often less than the screen resolution for faster rendering)
2178 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2179 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2180 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2182 // calculate desired texture sizes
2183 if (gl_support_arb_texture_non_power_of_two)
2185 screentexturewidth = r_view.width;
2186 screentextureheight = r_view.height;
2187 bloomtexturewidth = r_bloomstate.bloomwidth;
2188 bloomtextureheight = r_bloomstate.bloomheight;
2192 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2193 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2194 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2195 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2200 screentexturewidth = screentextureheight = 0;
2202 else if (r_bloom.integer)
2207 screentexturewidth = screentextureheight = 0;
2208 bloomtexturewidth = bloomtextureheight = 0;
2211 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)
2213 // can't use bloom if the parameters are too weird
2214 // can't use bloom if the card does not support the texture size
2215 if (r_bloomstate.texture_screen)
2216 R_FreeTexture(r_bloomstate.texture_screen);
2217 if (r_bloomstate.texture_bloom)
2218 R_FreeTexture(r_bloomstate.texture_bloom);
2219 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2223 r_bloomstate.enabled = true;
2224 r_bloomstate.hdr = r_hdr.integer != 0;
2226 // allocate textures as needed
2227 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2229 if (r_bloomstate.texture_screen)
2230 R_FreeTexture(r_bloomstate.texture_screen);
2231 r_bloomstate.texture_screen = NULL;
2232 r_bloomstate.screentexturewidth = screentexturewidth;
2233 r_bloomstate.screentextureheight = screentextureheight;
2234 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2235 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);
2237 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2239 if (r_bloomstate.texture_bloom)
2240 R_FreeTexture(r_bloomstate.texture_bloom);
2241 r_bloomstate.texture_bloom = NULL;
2242 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2243 r_bloomstate.bloomtextureheight = bloomtextureheight;
2244 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2245 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);
2248 // set up a texcoord array for the full resolution screen image
2249 // (we have to keep this around to copy back during final render)
2250 r_bloomstate.screentexcoord2f[0] = 0;
2251 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2252 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2253 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2254 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2255 r_bloomstate.screentexcoord2f[5] = 0;
2256 r_bloomstate.screentexcoord2f[6] = 0;
2257 r_bloomstate.screentexcoord2f[7] = 0;
2259 // set up a texcoord array for the reduced resolution bloom image
2260 // (which will be additive blended over the screen image)
2261 r_bloomstate.bloomtexcoord2f[0] = 0;
2262 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2263 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2264 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2265 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2266 r_bloomstate.bloomtexcoord2f[5] = 0;
2267 r_bloomstate.bloomtexcoord2f[6] = 0;
2268 r_bloomstate.bloomtexcoord2f[7] = 0;
2271 void R_Bloom_CopyScreenTexture(float colorscale)
2273 r_refdef.stats.bloom++;
2275 R_ResetViewRendering2D();
2276 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2277 R_Mesh_ColorPointer(NULL, 0, 0);
2278 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2279 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2281 // copy view into the screen texture
2282 GL_ActiveTexture(0);
2284 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
2285 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2287 // now scale it down to the bloom texture size
2289 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2290 GL_BlendFunc(GL_ONE, GL_ZERO);
2291 GL_Color(colorscale, colorscale, colorscale, 1);
2292 // TODO: optimize with multitexture or GLSL
2293 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2294 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2296 // we now have a bloom image in the framebuffer
2297 // copy it into the bloom image texture for later processing
2298 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2299 GL_ActiveTexture(0);
2301 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
2302 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2305 void R_Bloom_CopyHDRTexture(void)
2307 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2308 GL_ActiveTexture(0);
2310 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
2311 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2314 void R_Bloom_MakeTexture(void)
2317 float xoffset, yoffset, r, brighten;
2319 r_refdef.stats.bloom++;
2321 R_ResetViewRendering2D();
2322 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2323 R_Mesh_ColorPointer(NULL, 0, 0);
2325 // we have a bloom image in the framebuffer
2327 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2329 for (x = 1;x < r_bloom_colorexponent.value;)
2332 r = bound(0, r_bloom_colorexponent.value / x, 1);
2333 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2334 GL_Color(r, r, r, 1);
2335 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2336 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2337 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2338 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2340 // copy the vertically blurred bloom view to a texture
2341 GL_ActiveTexture(0);
2343 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
2344 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2347 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2348 brighten = r_bloom_brighten.value;
2350 brighten *= r_hdr_range.value;
2351 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2352 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2354 for (dir = 0;dir < 2;dir++)
2356 // blend on at multiple vertical offsets to achieve a vertical blur
2357 // TODO: do offset blends using GLSL
2358 GL_BlendFunc(GL_ONE, GL_ZERO);
2359 for (x = -range;x <= range;x++)
2361 if (!dir){xoffset = 0;yoffset = x;}
2362 else {xoffset = x;yoffset = 0;}
2363 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2364 yoffset /= (float)r_bloomstate.bloomtextureheight;
2365 // compute a texcoord array with the specified x and y offset
2366 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2367 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2368 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2369 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2370 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2371 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2372 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2373 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2374 // this r value looks like a 'dot' particle, fading sharply to
2375 // black at the edges
2376 // (probably not realistic but looks good enough)
2377 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2378 //r = (dir ? 1.0f : brighten)/(range*2+1);
2379 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2380 GL_Color(r, r, r, 1);
2381 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2382 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2383 GL_BlendFunc(GL_ONE, GL_ONE);
2386 // copy the vertically blurred bloom view to a texture
2387 GL_ActiveTexture(0);
2389 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
2390 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2393 // apply subtract last
2394 // (just like it would be in a GLSL shader)
2395 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2397 GL_BlendFunc(GL_ONE, GL_ZERO);
2398 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2399 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2400 GL_Color(1, 1, 1, 1);
2401 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2402 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2404 GL_BlendFunc(GL_ONE, GL_ONE);
2405 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2406 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2407 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2408 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2409 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2410 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2411 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2413 // copy the darkened bloom view to a texture
2414 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2415 GL_ActiveTexture(0);
2417 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
2418 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2422 void R_HDR_RenderBloomTexture(void)
2424 int oldwidth, oldheight;
2426 oldwidth = r_view.width;
2427 oldheight = r_view.height;
2428 r_view.width = r_bloomstate.bloomwidth;
2429 r_view.height = r_bloomstate.bloomheight;
2431 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2432 // TODO: add exposure compensation features
2433 // TODO: add fp16 framebuffer support
2435 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2437 r_view.colorscale /= r_hdr_range.value;
2440 R_ResetViewRendering2D();
2442 R_Bloom_CopyHDRTexture();
2443 R_Bloom_MakeTexture();
2445 R_ResetViewRendering3D();
2448 if (r_timereport_active)
2449 R_TimeReport("clear");
2452 // restore the view settings
2453 r_view.width = oldwidth;
2454 r_view.height = oldheight;
2457 static void R_BlendView(void)
2459 if (r_bloomstate.enabled && r_bloomstate.hdr)
2461 // render high dynamic range bloom effect
2462 // the bloom texture was made earlier this render, so we just need to
2463 // blend it onto the screen...
2464 R_ResetViewRendering2D();
2465 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2466 R_Mesh_ColorPointer(NULL, 0, 0);
2467 GL_Color(1, 1, 1, 1);
2468 GL_BlendFunc(GL_ONE, GL_ONE);
2469 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2470 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 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 else if (r_bloomstate.enabled)
2476 // render simple bloom effect
2477 // copy the screen and shrink it and darken it for the bloom process
2478 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2479 // make the bloom texture
2480 R_Bloom_MakeTexture();
2481 // put the original screen image back in place and blend the bloom
2483 R_ResetViewRendering2D();
2484 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2485 R_Mesh_ColorPointer(NULL, 0, 0);
2486 GL_Color(1, 1, 1, 1);
2487 GL_BlendFunc(GL_ONE, GL_ZERO);
2488 // do both in one pass if possible
2489 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2490 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2491 if (r_textureunits.integer >= 2 && gl_combine.integer)
2493 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2494 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2495 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2499 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2500 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2501 // now blend on the bloom texture
2502 GL_BlendFunc(GL_ONE, GL_ONE);
2503 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2504 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2506 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2507 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2509 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2511 // apply a color tint to the whole view
2512 R_ResetViewRendering2D();
2513 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2514 R_Mesh_ColorPointer(NULL, 0, 0);
2515 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2516 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2517 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2521 void R_RenderScene(void);
2523 matrix4x4_t r_waterscrollmatrix;
2525 void R_UpdateVariables(void)
2529 r_refdef.farclip = 4096;
2530 if (r_refdef.worldmodel)
2531 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2532 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2534 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2535 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2536 r_refdef.polygonfactor = 0;
2537 r_refdef.polygonoffset = 0;
2538 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2539 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2541 r_refdef.rtworld = r_shadow_realtime_world.integer;
2542 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2543 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2544 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2545 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2546 if (r_showsurfaces.integer)
2548 r_refdef.rtworld = false;
2549 r_refdef.rtworldshadows = false;
2550 r_refdef.rtdlight = false;
2551 r_refdef.rtdlightshadows = false;
2552 r_refdef.lightmapintensity = 0;
2555 if (gamemode == GAME_NEHAHRA)
2557 if (gl_fogenable.integer)
2559 r_refdef.oldgl_fogenable = true;
2560 r_refdef.fog_density = gl_fogdensity.value;
2561 r_refdef.fog_red = gl_fogred.value;
2562 r_refdef.fog_green = gl_foggreen.value;
2563 r_refdef.fog_blue = gl_fogblue.value;
2565 else if (r_refdef.oldgl_fogenable)
2567 r_refdef.oldgl_fogenable = false;
2568 r_refdef.fog_density = 0;
2569 r_refdef.fog_red = 0;
2570 r_refdef.fog_green = 0;
2571 r_refdef.fog_blue = 0;
2574 if (r_refdef.fog_density)
2576 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2577 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2578 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2580 if (r_refdef.fog_density)
2582 r_refdef.fogenabled = true;
2583 // this is the point where the fog reaches 0.9986 alpha, which we
2584 // consider a good enough cutoff point for the texture
2585 // (0.9986 * 256 == 255.6)
2586 r_refdef.fogrange = 400 / r_refdef.fog_density;
2587 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2588 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2589 // fog color was already set
2592 r_refdef.fogenabled = false;
2600 void R_RenderView(void)
2602 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2603 return; //Host_Error ("R_RenderView: NULL worldmodel");
2605 R_Shadow_UpdateWorldLightSelection();
2608 if (r_timereport_active)
2609 R_TimeReport("setup");
2612 if (r_timereport_active)
2613 R_TimeReport("visibility");
2615 R_ResetViewRendering3D();
2618 if (r_timereport_active)
2619 R_TimeReport("clear");
2621 R_Bloom_StartFrame();
2623 // this produces a bloom texture to be used in R_BlendView() later
2625 R_HDR_RenderBloomTexture();
2627 r_view.colorscale = r_hdr_scenebrightness.value;
2631 if (r_timereport_active)
2632 R_TimeReport("blendview");
2634 GL_Scissor(0, 0, vid.width, vid.height);
2635 GL_ScissorTest(false);
2639 extern void R_DrawLightningBeams (void);
2640 extern void VM_CL_AddPolygonsToMeshQueue (void);
2641 extern void R_DrawPortals (void);
2642 extern cvar_t cl_locs_show;
2643 static void R_DrawLocs(void);
2644 static void R_DrawEntityBBoxes(void);
2645 void R_RenderScene(void)
2647 // don't let sound skip if going slow
2648 if (r_refdef.extraupdate)
2651 R_ResetViewRendering3D();
2653 R_MeshQueue_BeginScene();
2657 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);
2659 if (cl.csqc_vidvars.drawworld)
2661 // don't let sound skip if going slow
2662 if (r_refdef.extraupdate)
2665 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2667 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2668 if (r_timereport_active)
2669 R_TimeReport("worldsky");
2672 if (R_DrawBrushModelsSky() && r_timereport_active)
2673 R_TimeReport("bmodelsky");
2676 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2678 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2679 if (r_timereport_active)
2680 R_TimeReport("worlddepth");
2682 if (r_depthfirst.integer >= 2)
2684 R_DrawModelsDepth();
2685 if (r_timereport_active)
2686 R_TimeReport("modeldepth");
2689 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2691 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2692 if (r_timereport_active)
2693 R_TimeReport("world");
2696 // don't let sound skip if going slow
2697 if (r_refdef.extraupdate)
2701 if (r_timereport_active)
2702 R_TimeReport("models");
2704 // don't let sound skip if going slow
2705 if (r_refdef.extraupdate)
2708 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2710 R_DrawModelShadows();
2712 R_ResetViewRendering3D();
2714 // don't let sound skip if going slow
2715 if (r_refdef.extraupdate)
2719 R_ShadowVolumeLighting(false);
2720 if (r_timereport_active)
2721 R_TimeReport("rtlights");
2723 // don't let sound skip if going slow
2724 if (r_refdef.extraupdate)
2727 if (cl.csqc_vidvars.drawworld)
2729 R_DrawLightningBeams();
2730 if (r_timereport_active)
2731 R_TimeReport("lightning");
2734 if (r_timereport_active)
2735 R_TimeReport("particles");
2738 if (r_timereport_active)
2739 R_TimeReport("explosions");
2742 if (gl_support_fragment_shader)
2744 qglUseProgramObjectARB(0);CHECKGLERROR
2746 VM_CL_AddPolygonsToMeshQueue();
2748 if (cl_locs_show.integer)
2751 if (r_timereport_active)
2752 R_TimeReport("showlocs");
2755 if (r_drawportals.integer)
2758 if (r_timereport_active)
2759 R_TimeReport("portals");
2762 if (r_showbboxes.value > 0)
2764 R_DrawEntityBBoxes();
2765 if (r_timereport_active)
2766 R_TimeReport("bboxes");
2769 if (gl_support_fragment_shader)
2771 qglUseProgramObjectARB(0);CHECKGLERROR
2773 R_MeshQueue_RenderTransparent();
2774 if (r_timereport_active)
2775 R_TimeReport("drawtrans");
2777 if (gl_support_fragment_shader)
2779 qglUseProgramObjectARB(0);CHECKGLERROR
2782 if (cl.csqc_vidvars.drawworld)
2785 if (r_timereport_active)
2786 R_TimeReport("coronas");
2789 // don't let sound skip if going slow
2790 if (r_refdef.extraupdate)
2793 R_ResetViewRendering2D();
2796 static const int bboxelements[36] =
2806 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2809 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2810 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2811 GL_DepthMask(false);
2812 GL_DepthRange(0, 1);
2813 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2814 R_Mesh_Matrix(&identitymatrix);
2815 R_Mesh_ResetTextureState();
2817 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2818 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2819 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2820 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2821 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2822 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2823 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2824 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2825 R_FillColors(color4f, 8, cr, cg, cb, ca);
2826 if (r_refdef.fogenabled)
2828 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2830 f1 = FogPoint_World(v);
2832 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2833 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2834 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2837 R_Mesh_VertexPointer(vertex3f, 0, 0);
2838 R_Mesh_ColorPointer(color4f, 0, 0);
2839 R_Mesh_ResetTextureState();
2840 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2843 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2847 prvm_edict_t *edict;
2848 // this function draws bounding boxes of server entities
2852 for (i = 0;i < numsurfaces;i++)
2854 edict = PRVM_EDICT_NUM(surfacelist[i]);
2855 switch ((int)edict->fields.server->solid)
2857 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2858 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2859 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2860 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2861 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2862 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2864 color[3] *= r_showbboxes.value;
2865 color[3] = bound(0, color[3], 1);
2866 GL_DepthTest(!r_showdisabledepthtest.integer);
2867 GL_CullFace(GL_BACK);
2868 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2873 static void R_DrawEntityBBoxes(void)
2876 prvm_edict_t *edict;
2878 // this function draws bounding boxes of server entities
2882 for (i = 0;i < prog->num_edicts;i++)
2884 edict = PRVM_EDICT_NUM(i);
2885 if (edict->priv.server->free)
2887 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2888 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2893 int nomodelelements[24] =
2905 float nomodelvertex3f[6*3] =
2915 float nomodelcolor4f[6*4] =
2917 0.0f, 0.0f, 0.5f, 1.0f,
2918 0.0f, 0.0f, 0.5f, 1.0f,
2919 0.0f, 0.5f, 0.0f, 1.0f,
2920 0.0f, 0.5f, 0.0f, 1.0f,
2921 0.5f, 0.0f, 0.0f, 1.0f,
2922 0.5f, 0.0f, 0.0f, 1.0f
2925 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2930 // this is only called once per entity so numsurfaces is always 1, and
2931 // surfacelist is always {0}, so this code does not handle batches
2932 R_Mesh_Matrix(&ent->matrix);
2934 if (ent->flags & EF_ADDITIVE)
2936 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2937 GL_DepthMask(false);
2939 else if (ent->alpha < 1)
2941 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2942 GL_DepthMask(false);
2946 GL_BlendFunc(GL_ONE, GL_ZERO);
2949 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2950 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2951 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2952 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2953 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2954 if (r_refdef.fogenabled)
2957 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2958 R_Mesh_ColorPointer(color4f, 0, 0);
2959 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2960 f1 = FogPoint_World(org);
2962 for (i = 0, c = color4f;i < 6;i++, c += 4)
2964 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2965 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2966 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2970 else if (ent->alpha != 1)
2972 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2973 R_Mesh_ColorPointer(color4f, 0, 0);
2974 for (i = 0, c = color4f;i < 6;i++, c += 4)
2978 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2979 R_Mesh_ResetTextureState();
2980 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2983 void R_DrawNoModel(entity_render_t *ent)
2986 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2987 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2988 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2990 // R_DrawNoModelCallback(ent, 0);
2993 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2995 vec3_t right1, right2, diff, normal;
2997 VectorSubtract (org2, org1, normal);
2999 // calculate 'right' vector for start
3000 VectorSubtract (r_view.origin, org1, diff);
3001 CrossProduct (normal, diff, right1);
3002 VectorNormalize (right1);
3004 // calculate 'right' vector for end
3005 VectorSubtract (r_view.origin, org2, diff);
3006 CrossProduct (normal, diff, right2);
3007 VectorNormalize (right2);
3009 vert[ 0] = org1[0] + width * right1[0];
3010 vert[ 1] = org1[1] + width * right1[1];
3011 vert[ 2] = org1[2] + width * right1[2];
3012 vert[ 3] = org1[0] - width * right1[0];
3013 vert[ 4] = org1[1] - width * right1[1];
3014 vert[ 5] = org1[2] - width * right1[2];
3015 vert[ 6] = org2[0] - width * right2[0];
3016 vert[ 7] = org2[1] - width * right2[1];
3017 vert[ 8] = org2[2] - width * right2[2];
3018 vert[ 9] = org2[0] + width * right2[0];
3019 vert[10] = org2[1] + width * right2[1];
3020 vert[11] = org2[2] + width * right2[2];
3023 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3025 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)
3030 if (r_refdef.fogenabled)
3031 fog = FogPoint_World(origin);
3033 R_Mesh_Matrix(&identitymatrix);
3034 GL_BlendFunc(blendfunc1, blendfunc2);
3040 GL_CullFace(GL_BACK);
3043 GL_CullFace(GL_FRONT);
3045 GL_DepthMask(false);
3046 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3047 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3048 GL_DepthTest(!depthdisable);
3050 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3051 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3052 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3053 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3054 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3055 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3056 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3057 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3058 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3059 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3060 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3061 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3063 R_Mesh_VertexPointer(vertex3f, 0, 0);
3064 R_Mesh_ColorPointer(NULL, 0, 0);
3065 R_Mesh_ResetTextureState();
3066 R_Mesh_TexBind(0, R_GetTexture(texture));
3067 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3068 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3069 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3070 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3072 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3074 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3075 GL_BlendFunc(blendfunc1, GL_ONE);
3077 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);
3078 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3082 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3087 VectorSet(v, x, y, z);
3088 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3089 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3091 if (i == mesh->numvertices)
3093 if (mesh->numvertices < mesh->maxvertices)
3095 VectorCopy(v, vertex3f);
3096 mesh->numvertices++;
3098 return mesh->numvertices;
3104 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3108 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3109 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3110 e = mesh->element3i + mesh->numtriangles * 3;
3111 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3113 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3114 if (mesh->numtriangles < mesh->maxtriangles)
3119 mesh->numtriangles++;
3121 element[1] = element[2];
3125 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3129 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3130 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3131 e = mesh->element3i + mesh->numtriangles * 3;
3132 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3134 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3135 if (mesh->numtriangles < mesh->maxtriangles)
3140 mesh->numtriangles++;
3142 element[1] = element[2];
3146 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3147 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3149 int planenum, planenum2;
3152 mplane_t *plane, *plane2;
3154 double temppoints[2][256*3];
3155 // figure out how large a bounding box we need to properly compute this brush
3157 for (w = 0;w < numplanes;w++)
3158 maxdist = max(maxdist, planes[w].dist);
3159 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3160 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3161 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3165 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3166 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3168 if (planenum2 == planenum)
3170 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);
3173 if (tempnumpoints < 3)
3175 // generate elements forming a triangle fan for this polygon
3176 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3180 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3183 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3184 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3185 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);
3186 GL_LockArrays(0, brush->numpoints);
3187 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3188 GL_LockArrays(0, 0);
3191 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3194 if (!surface->num_collisiontriangles)
3196 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3197 i = (int)(((size_t)surface) / sizeof(msurface_t));
3198 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);
3199 GL_LockArrays(0, surface->num_collisionvertices);
3200 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3201 GL_LockArrays(0, 0);
3204 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)
3206 texturelayer_t *layer;
3207 layer = t->currentlayers + t->currentnumlayers++;
3209 layer->depthmask = depthmask;
3210 layer->blendfunc1 = blendfunc1;
3211 layer->blendfunc2 = blendfunc2;
3212 layer->texture = texture;
3213 layer->texmatrix = *matrix;
3214 layer->color[0] = r * r_view.colorscale;
3215 layer->color[1] = g * r_view.colorscale;
3216 layer->color[2] = b * r_view.colorscale;
3217 layer->color[3] = a;
3220 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3223 index = parms[2] + r_refdef.time * parms[3];
3224 index -= floor(index);
3228 case Q3WAVEFUNC_NONE:
3229 case Q3WAVEFUNC_NOISE:
3230 case Q3WAVEFUNC_COUNT:
3233 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3234 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3235 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3236 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3237 case Q3WAVEFUNC_TRIANGLE:
3239 f = index - floor(index);
3250 return (float)(parms[0] + parms[1] * f);
3253 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3256 model_t *model = ent->model;
3259 q3shaderinfo_layer_tcmod_t *tcmod;
3261 // switch to an alternate material if this is a q1bsp animated material
3263 texture_t *texture = t;
3264 int s = ent->skinnum;
3265 if ((unsigned int)s >= (unsigned int)model->numskins)
3267 if (model->skinscenes)
3269 if (model->skinscenes[s].framecount > 1)
3270 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3272 s = model->skinscenes[s].firstframe;
3275 t = t + s * model->num_surfaces;
3278 // use an alternate animation if the entity's frame is not 0,
3279 // and only if the texture has an alternate animation
3280 if (ent->frame2 != 0 && t->anim_total[1])
3281 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3283 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3285 texture->currentframe = t;
3288 // update currentskinframe to be a qw skin or animation frame
3289 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3291 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3293 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3294 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3295 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);
3297 t->currentskinframe = r_qwskincache_skinframe[i];
3298 if (t->currentskinframe == NULL)
3299 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3301 else if (t->numskinframes >= 2)
3302 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3303 if (t->backgroundnumskinframes >= 2)
3304 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3306 t->currentmaterialflags = t->basematerialflags;
3307 t->currentalpha = ent->alpha;
3308 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3309 t->currentalpha *= r_wateralpha.value;
3310 if (!(ent->flags & RENDER_LIGHT))
3311 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3312 if (ent->effects & EF_ADDITIVE)
3313 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3314 else if (t->currentalpha < 1)
3315 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3316 if (ent->effects & EF_DOUBLESIDED)
3317 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3318 if (ent->effects & EF_NODEPTHTEST)
3319 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3320 if (ent->flags & RENDER_VIEWMODEL)
3321 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3322 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3323 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3325 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3328 switch(tcmod->tcmod)
3332 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3333 matrix = r_waterscrollmatrix;
3335 matrix = identitymatrix;
3337 case Q3TCMOD_ENTITYTRANSLATE:
3338 // this is used in Q3 to allow the gamecode to control texcoord
3339 // scrolling on the entity, which is not supported in darkplaces yet.
3340 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3342 case Q3TCMOD_ROTATE:
3343 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3344 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3345 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3348 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3350 case Q3TCMOD_SCROLL:
3351 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3353 case Q3TCMOD_STRETCH:
3354 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3355 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3357 case Q3TCMOD_TRANSFORM:
3358 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3359 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3360 VectorSet(tcmat + 6, 0 , 0 , 1);
3361 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3362 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3364 case Q3TCMOD_TURBULENT:
3365 // this is handled in the RSurf_PrepareVertices function
3366 matrix = identitymatrix;
3369 // either replace or concatenate the transformation
3371 t->currenttexmatrix = matrix;
3374 matrix4x4_t temp = t->currenttexmatrix;
3375 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3379 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3380 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3381 t->glosstexture = r_texture_white;
3382 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3383 t->backgroundglosstexture = r_texture_white;
3384 t->specularpower = r_shadow_glossexponent.value;
3385 // TODO: store reference values for these in the texture?
3386 t->specularscale = 0;
3387 if (r_shadow_gloss.integer > 0)
3389 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3391 if (r_shadow_glossintensity.value > 0)
3393 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3394 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3395 t->specularscale = r_shadow_glossintensity.value;
3398 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3399 t->specularscale = r_shadow_gloss2intensity.value;
3402 t->currentpolygonfactor = r_refdef.polygonfactor;
3403 t->currentpolygonoffset = r_refdef.polygonoffset;
3404 // submodels are biased to avoid z-fighting with world surfaces that they
3405 // may be exactly overlapping (avoids z-fighting artifacts on certain
3406 // doors and things in Quake maps)
3407 if (ent->model->brush.submodel)
3409 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3410 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3413 VectorClear(t->dlightcolor);
3414 t->currentnumlayers = 0;
3415 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3417 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3419 int blendfunc1, blendfunc2, depthmask;
3420 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3422 blendfunc1 = GL_SRC_ALPHA;
3423 blendfunc2 = GL_ONE;
3425 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3427 blendfunc1 = GL_SRC_ALPHA;
3428 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3430 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3432 blendfunc1 = t->customblendfunc[0];
3433 blendfunc2 = t->customblendfunc[1];
3437 blendfunc1 = GL_ONE;
3438 blendfunc2 = GL_ZERO;
3440 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3441 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3443 rtexture_t *currentbasetexture;
3445 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3446 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3447 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3448 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3450 // fullbright is not affected by r_refdef.lightmapintensity
3451 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3452 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3453 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);
3454 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3455 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);
3460 // set the color tint used for lights affecting this surface
3461 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3463 // q3bsp has no lightmap updates, so the lightstylevalue that
3464 // would normally be baked into the lightmap must be
3465 // applied to the color
3466 if (ent->model->type == mod_brushq3)
3467 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3468 colorscale *= r_refdef.lightmapintensity;
3469 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);
3470 if (r_ambient.value >= (1.0f/64.0f))
3471 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);
3472 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3474 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);
3475 if (r_ambient.value >= (1.0f/64.0f))
3476 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);
3478 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3480 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);
3481 if (r_ambient.value >= (1.0f/64.0f))
3482 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);
3485 if (t->currentskinframe->glow != NULL)
3486 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);
3487 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3489 // if this is opaque use alpha blend which will darken the earlier
3492 // if this is an alpha blended material, all the earlier passes
3493 // were darkened by fog already, so we only need to add the fog
3494 // color ontop through the fog mask texture
3496 // if this is an additive blended material, all the earlier passes
3497 // were darkened by fog already, and we should not add fog color
3498 // (because the background was not darkened, there is no fog color
3499 // that was lost behind it).
3500 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);
3507 void R_UpdateAllTextureInfo(entity_render_t *ent)
3511 for (i = 0;i < ent->model->num_texturesperskin;i++)
3512 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3515 rsurfacestate_t rsurface;
3517 void R_Mesh_ResizeArrays(int newvertices)
3520 if (rsurface.array_size >= newvertices)
3522 if (rsurface.array_modelvertex3f)
3523 Mem_Free(rsurface.array_modelvertex3f);
3524 rsurface.array_size = (newvertices + 1023) & ~1023;
3525 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3526 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3527 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3528 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3529 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3530 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3531 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3532 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3533 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3534 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3535 rsurface.array_color4f = base + rsurface.array_size * 27;
3536 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3539 void RSurf_CleanUp(void)
3542 if (rsurface.mode == RSURFMODE_GLSL)
3544 qglUseProgramObjectARB(0);CHECKGLERROR
3546 GL_AlphaTest(false);
3547 rsurface.mode = RSURFMODE_NONE;
3548 rsurface.uselightmaptexture = false;
3549 rsurface.texture = NULL;
3552 void RSurf_ActiveWorldEntity(void)
3554 model_t *model = r_refdef.worldmodel;
3556 if (rsurface.array_size < model->surfmesh.num_vertices)
3557 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3558 rsurface.matrix = identitymatrix;
3559 rsurface.inversematrix = identitymatrix;
3560 R_Mesh_Matrix(&identitymatrix);
3561 VectorCopy(r_view.origin, rsurface.modelorg);
3562 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3563 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3564 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3565 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3566 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3567 rsurface.frameblend[0].frame = 0;
3568 rsurface.frameblend[0].lerp = 1;
3569 rsurface.frameblend[1].frame = 0;
3570 rsurface.frameblend[1].lerp = 0;
3571 rsurface.frameblend[2].frame = 0;
3572 rsurface.frameblend[2].lerp = 0;
3573 rsurface.frameblend[3].frame = 0;
3574 rsurface.frameblend[3].lerp = 0;
3575 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3576 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3577 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3578 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3579 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3580 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3581 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3582 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3583 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3584 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3585 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3586 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3587 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3588 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3589 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3590 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3591 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3592 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3593 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3594 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3595 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3596 rsurface.modelelement3i = model->surfmesh.data_element3i;
3597 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3598 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3599 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3600 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3601 rsurface.modelsurfaces = model->data_surfaces;
3602 rsurface.generatedvertex = false;
3603 rsurface.vertex3f = rsurface.modelvertex3f;
3604 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3605 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3606 rsurface.svector3f = rsurface.modelsvector3f;
3607 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3608 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3609 rsurface.tvector3f = rsurface.modeltvector3f;
3610 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3611 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3612 rsurface.normal3f = rsurface.modelnormal3f;
3613 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3614 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3615 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3618 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3620 model_t *model = ent->model;
3622 if (rsurface.array_size < model->surfmesh.num_vertices)
3623 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3624 rsurface.matrix = ent->matrix;
3625 rsurface.inversematrix = ent->inversematrix;
3626 R_Mesh_Matrix(&rsurface.matrix);
3627 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3628 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3629 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3630 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3631 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3632 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3633 rsurface.frameblend[0] = ent->frameblend[0];
3634 rsurface.frameblend[1] = ent->frameblend[1];
3635 rsurface.frameblend[2] = ent->frameblend[2];
3636 rsurface.frameblend[3] = ent->frameblend[3];
3637 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3641 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3642 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3643 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3644 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3645 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3647 else if (wantnormals)
3649 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3650 rsurface.modelsvector3f = NULL;
3651 rsurface.modeltvector3f = NULL;
3652 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3653 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3657 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3658 rsurface.modelsvector3f = NULL;
3659 rsurface.modeltvector3f = NULL;
3660 rsurface.modelnormal3f = NULL;
3661 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3663 rsurface.modelvertex3f_bufferobject = 0;
3664 rsurface.modelvertex3f_bufferoffset = 0;
3665 rsurface.modelsvector3f_bufferobject = 0;
3666 rsurface.modelsvector3f_bufferoffset = 0;
3667 rsurface.modeltvector3f_bufferobject = 0;
3668 rsurface.modeltvector3f_bufferoffset = 0;
3669 rsurface.modelnormal3f_bufferobject = 0;
3670 rsurface.modelnormal3f_bufferoffset = 0;
3671 rsurface.generatedvertex = true;
3675 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3676 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3677 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3678 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3679 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3680 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3681 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3682 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3683 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3684 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3685 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3686 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3687 rsurface.generatedvertex = false;
3689 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3690 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3691 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3692 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3693 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3694 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3695 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3696 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3697 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3698 rsurface.modelelement3i = model->surfmesh.data_element3i;
3699 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3700 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3701 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3702 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3703 rsurface.modelsurfaces = model->data_surfaces;
3704 rsurface.vertex3f = rsurface.modelvertex3f;
3705 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3706 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3707 rsurface.svector3f = rsurface.modelsvector3f;
3708 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3709 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3710 rsurface.tvector3f = rsurface.modeltvector3f;
3711 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3712 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3713 rsurface.normal3f = rsurface.modelnormal3f;
3714 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3715 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3716 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3719 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3720 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3723 int texturesurfaceindex;
3728 const float *v1, *in_tc;
3730 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3732 q3shaderinfo_deform_t *deform;
3733 // 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
3734 if (rsurface.generatedvertex)
3736 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3737 generatenormals = true;
3738 for (i = 0;i < Q3MAXDEFORMS;i++)
3740 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3742 generatetangents = true;
3743 generatenormals = true;
3745 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3746 generatenormals = true;
3748 if (generatenormals && !rsurface.modelnormal3f)
3750 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3751 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3752 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3753 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3755 if (generatetangents && !rsurface.modelsvector3f)
3757 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3758 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3759 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3760 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3761 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3762 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3763 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);
3766 rsurface.vertex3f = rsurface.modelvertex3f;
3767 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3768 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3769 rsurface.svector3f = rsurface.modelsvector3f;
3770 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3771 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3772 rsurface.tvector3f = rsurface.modeltvector3f;
3773 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3774 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3775 rsurface.normal3f = rsurface.modelnormal3f;
3776 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3777 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3778 // if vertices are deformed (sprite flares and things in maps, possibly
3779 // water waves, bulges and other deformations), generate them into
3780 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3781 // (may be static model data or generated data for an animated model, or
3782 // the previous deform pass)
3783 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3785 switch (deform->deform)
3788 case Q3DEFORM_PROJECTIONSHADOW:
3789 case Q3DEFORM_TEXT0:
3790 case Q3DEFORM_TEXT1:
3791 case Q3DEFORM_TEXT2:
3792 case Q3DEFORM_TEXT3:
3793 case Q3DEFORM_TEXT4:
3794 case Q3DEFORM_TEXT5:
3795 case Q3DEFORM_TEXT6:
3796 case Q3DEFORM_TEXT7:
3799 case Q3DEFORM_AUTOSPRITE:
3800 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3801 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3802 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3803 VectorNormalize(newforward);
3804 VectorNormalize(newright);
3805 VectorNormalize(newup);
3806 // make deformed versions of only the model vertices used by the specified surfaces
3807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3809 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3810 // a single autosprite surface can contain multiple sprites...
3811 for (j = 0;j < surface->num_vertices - 3;j += 4)
3813 VectorClear(center);
3814 for (i = 0;i < 4;i++)
3815 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3816 VectorScale(center, 0.25f, center);
3817 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3818 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3819 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3820 for (i = 0;i < 4;i++)
3822 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3823 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3826 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);
3827 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);
3829 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3830 rsurface.vertex3f_bufferobject = 0;
3831 rsurface.vertex3f_bufferoffset = 0;
3832 rsurface.svector3f = rsurface.array_deformedsvector3f;
3833 rsurface.svector3f_bufferobject = 0;
3834 rsurface.svector3f_bufferoffset = 0;
3835 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3836 rsurface.tvector3f_bufferobject = 0;
3837 rsurface.tvector3f_bufferoffset = 0;
3838 rsurface.normal3f = rsurface.array_deformednormal3f;
3839 rsurface.normal3f_bufferobject = 0;
3840 rsurface.normal3f_bufferoffset = 0;
3842 case Q3DEFORM_AUTOSPRITE2:
3843 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3844 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3845 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3846 VectorNormalize(newforward);
3847 VectorNormalize(newright);
3848 VectorNormalize(newup);
3849 // make deformed versions of only the model vertices used by the specified surfaces
3850 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3852 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3853 const float *v1, *v2;
3863 memset(shortest, 0, sizeof(shortest));
3864 // a single autosprite surface can contain multiple sprites...
3865 for (j = 0;j < surface->num_vertices - 3;j += 4)
3867 VectorClear(center);
3868 for (i = 0;i < 4;i++)
3869 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3870 VectorScale(center, 0.25f, center);
3871 // find the two shortest edges, then use them to define the
3872 // axis vectors for rotating around the central axis
3873 for (i = 0;i < 6;i++)
3875 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3876 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3878 Debug_PolygonBegin(NULL, 0, false, 0);
3879 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
3880 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
3881 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
3884 l = VectorDistance2(v1, v2);
3885 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
3887 l += (1.0f / 1024.0f);
3888 if (shortest[0].length2 > l || i == 0)
3890 shortest[1] = shortest[0];
3891 shortest[0].length2 = l;
3892 shortest[0].v1 = v1;
3893 shortest[0].v2 = v2;
3895 else if (shortest[1].length2 > l || i == 1)
3897 shortest[1].length2 = l;
3898 shortest[1].v1 = v1;
3899 shortest[1].v2 = v2;
3902 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
3903 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
3905 Debug_PolygonBegin(NULL, 0, false, 0);
3906 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
3907 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
3908 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
3911 // this calculates the right vector from the shortest edge
3912 // and the up vector from the edge midpoints
3913 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
3914 VectorNormalize(right);
3915 VectorSubtract(end, start, up);
3916 VectorNormalize(up);
3917 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3918 //VectorSubtract(rsurface.modelorg, center, forward);
3919 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
3920 VectorNegate(forward, forward);
3921 VectorReflect(forward, 0, up, forward);
3922 VectorNormalize(forward);
3923 CrossProduct(up, forward, newright);
3924 VectorNormalize(newright);
3926 Debug_PolygonBegin(NULL, 0, false, 0);
3927 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
3928 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
3929 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3933 Debug_PolygonBegin(NULL, 0, false, 0);
3934 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
3935 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
3936 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3939 // rotate the quad around the up axis vector, this is made
3940 // especially easy by the fact we know the quad is flat,
3941 // so we only have to subtract the center position and
3942 // measure distance along the right vector, and then
3943 // multiply that by the newright vector and add back the
3945 // we also need to subtract the old position to undo the
3946 // displacement from the center, which we do with a
3947 // DotProduct, the subtraction/addition of center is also
3948 // optimized into DotProducts here
3949 l = DotProduct(right, center);
3950 for (i = 0;i < 4;i++)
3952 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3953 f = DotProduct(right, v1) - l;
3954 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3957 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);
3958 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);
3960 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3961 rsurface.vertex3f_bufferobject = 0;
3962 rsurface.vertex3f_bufferoffset = 0;
3963 rsurface.svector3f = rsurface.array_deformedsvector3f;
3964 rsurface.svector3f_bufferobject = 0;
3965 rsurface.svector3f_bufferoffset = 0;
3966 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3967 rsurface.tvector3f_bufferobject = 0;
3968 rsurface.tvector3f_bufferoffset = 0;
3969 rsurface.normal3f = rsurface.array_deformednormal3f;
3970 rsurface.normal3f_bufferobject = 0;
3971 rsurface.normal3f_bufferoffset = 0;
3973 case Q3DEFORM_NORMAL:
3974 // deform the normals to make reflections wavey
3975 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3977 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3978 for (j = 0;j < surface->num_vertices;j++)
3981 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
3982 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
3983 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
3984 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3985 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3986 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3987 VectorNormalize(normal);
3989 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);
3991 rsurface.svector3f = rsurface.array_deformedsvector3f;
3992 rsurface.svector3f_bufferobject = 0;
3993 rsurface.svector3f_bufferoffset = 0;
3994 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3995 rsurface.tvector3f_bufferobject = 0;
3996 rsurface.tvector3f_bufferoffset = 0;
3997 rsurface.normal3f = rsurface.array_deformednormal3f;
3998 rsurface.normal3f_bufferobject = 0;
3999 rsurface.normal3f_bufferoffset = 0;
4002 // deform vertex array to make wavey water and flags and such
4003 waveparms[0] = deform->waveparms[0];
4004 waveparms[1] = deform->waveparms[1];
4005 waveparms[2] = deform->waveparms[2];
4006 waveparms[3] = deform->waveparms[3];
4007 // this is how a divisor of vertex influence on deformation
4008 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4009 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4010 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4012 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4013 for (j = 0;j < surface->num_vertices;j++)
4015 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4016 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4017 // if the wavefunc depends on time, evaluate it per-vertex
4020 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4021 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4023 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4026 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4027 rsurface.vertex3f_bufferobject = 0;
4028 rsurface.vertex3f_bufferoffset = 0;
4030 case Q3DEFORM_BULGE:
4031 // deform vertex array to make the surface have moving bulges
4032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4034 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4035 for (j = 0;j < surface->num_vertices;j++)
4037 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4038 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4041 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4042 rsurface.vertex3f_bufferobject = 0;
4043 rsurface.vertex3f_bufferoffset = 0;
4046 // deform vertex array
4047 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4048 VectorScale(deform->parms, scale, waveparms);
4049 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4051 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4052 for (j = 0;j < surface->num_vertices;j++)
4053 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4055 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4056 rsurface.vertex3f_bufferobject = 0;
4057 rsurface.vertex3f_bufferoffset = 0;
4061 // generate texcoords based on the chosen texcoord source
4062 switch(rsurface.texture->tcgen.tcgen)
4065 case Q3TCGEN_TEXTURE:
4066 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4067 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4068 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4070 case Q3TCGEN_LIGHTMAP:
4071 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4072 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4073 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4075 case Q3TCGEN_VECTOR:
4076 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4078 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4079 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)
4081 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4082 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4085 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4086 rsurface.texcoordtexture2f_bufferobject = 0;
4087 rsurface.texcoordtexture2f_bufferoffset = 0;
4089 case Q3TCGEN_ENVIRONMENT:
4090 // make environment reflections using a spheremap
4091 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4093 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4094 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4095 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4096 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4097 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4099 float l, d, eyedir[3];
4100 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4101 l = 0.5f / VectorLength(eyedir);
4102 d = DotProduct(normal, eyedir)*2;
4103 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4104 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4107 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4108 rsurface.texcoordtexture2f_bufferobject = 0;
4109 rsurface.texcoordtexture2f_bufferoffset = 0;
4112 // the only tcmod that needs software vertex processing is turbulent, so
4113 // check for it here and apply the changes if needed
4114 // and we only support that as the first one
4115 // (handling a mixture of turbulent and other tcmods would be problematic
4116 // without punting it entirely to a software path)
4117 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4119 amplitude = rsurface.texture->tcmods[0].parms[1];
4120 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4121 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4123 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4124 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)
4126 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4127 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4130 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4131 rsurface.texcoordtexture2f_bufferobject = 0;
4132 rsurface.texcoordtexture2f_bufferoffset = 0;
4134 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4135 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4136 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4137 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4140 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4143 const msurface_t *surface = texturesurfacelist[0];
4144 const msurface_t *surface2;
4149 // TODO: lock all array ranges before render, rather than on each surface
4150 if (texturenumsurfaces == 1)
4152 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4153 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));
4155 else if (r_batchmode.integer == 2)
4157 #define MAXBATCHTRIANGLES 4096
4158 int batchtriangles = 0;
4159 int batchelements[MAXBATCHTRIANGLES*3];
4160 for (i = 0;i < texturenumsurfaces;i = j)
4162 surface = texturesurfacelist[i];
4164 if (surface->num_triangles > MAXBATCHTRIANGLES)
4166 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));
4169 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4170 batchtriangles = surface->num_triangles;
4171 firstvertex = surface->num_firstvertex;
4172 endvertex = surface->num_firstvertex + surface->num_vertices;
4173 for (;j < texturenumsurfaces;j++)
4175 surface2 = texturesurfacelist[j];
4176 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4178 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4179 batchtriangles += surface2->num_triangles;
4180 firstvertex = min(firstvertex, surface2->num_firstvertex);
4181 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4183 surface2 = texturesurfacelist[j-1];
4184 numvertices = endvertex - firstvertex;
4185 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4188 else if (r_batchmode.integer == 1)
4190 for (i = 0;i < texturenumsurfaces;i = j)
4192 surface = texturesurfacelist[i];
4193 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4194 if (texturesurfacelist[j] != surface2)
4196 surface2 = texturesurfacelist[j-1];
4197 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4198 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4199 GL_LockArrays(surface->num_firstvertex, numvertices);
4200 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4205 for (i = 0;i < texturenumsurfaces;i++)
4207 surface = texturesurfacelist[i];
4208 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4209 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4214 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4218 const msurface_t *surface = texturesurfacelist[0];
4219 const msurface_t *surface2;
4224 // TODO: lock all array ranges before render, rather than on each surface
4225 if (texturenumsurfaces == 1)
4227 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4228 if (deluxemaptexunit >= 0)
4229 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4230 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4231 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));
4233 else if (r_batchmode.integer == 2)
4235 #define MAXBATCHTRIANGLES 4096
4236 int batchtriangles = 0;
4237 int batchelements[MAXBATCHTRIANGLES*3];
4238 for (i = 0;i < texturenumsurfaces;i = j)
4240 surface = texturesurfacelist[i];
4241 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4242 if (deluxemaptexunit >= 0)
4243 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4245 if (surface->num_triangles > MAXBATCHTRIANGLES)
4247 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));
4250 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4251 batchtriangles = surface->num_triangles;
4252 firstvertex = surface->num_firstvertex;
4253 endvertex = surface->num_firstvertex + surface->num_vertices;
4254 for (;j < texturenumsurfaces;j++)
4256 surface2 = texturesurfacelist[j];
4257 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4259 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4260 batchtriangles += surface2->num_triangles;
4261 firstvertex = min(firstvertex, surface2->num_firstvertex);
4262 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4264 surface2 = texturesurfacelist[j-1];
4265 numvertices = endvertex - firstvertex;
4266 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4269 else if (r_batchmode.integer == 1)
4272 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4273 for (i = 0;i < texturenumsurfaces;i = j)
4275 surface = texturesurfacelist[i];
4276 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4277 if (texturesurfacelist[j] != surface2)
4279 Con_Printf(" %i", j - i);
4282 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4284 for (i = 0;i < texturenumsurfaces;i = j)
4286 surface = texturesurfacelist[i];
4287 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4288 if (deluxemaptexunit >= 0)
4289 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4290 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4291 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4294 Con_Printf(" %i", j - i);
4296 surface2 = texturesurfacelist[j-1];
4297 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4298 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4299 GL_LockArrays(surface->num_firstvertex, numvertices);
4300 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4308 for (i = 0;i < texturenumsurfaces;i++)
4310 surface = texturesurfacelist[i];
4311 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4312 if (deluxemaptexunit >= 0)
4313 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4314 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4315 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));
4320 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4323 int texturesurfaceindex;
4324 if (r_showsurfaces.integer == 2)
4326 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4328 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4329 for (j = 0;j < surface->num_triangles;j++)
4331 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4332 GL_Color(f, f, f, 1);
4333 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)));
4339 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4341 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4342 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4343 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);
4344 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4345 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));
4350 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4352 int texturesurfaceindex;
4356 if (rsurface.lightmapcolor4f)
4358 // generate color arrays for the surfaces in this list
4359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4362 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)
4364 f = FogPoint_Model(v);
4374 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4376 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4377 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)
4379 f = FogPoint_Model(v);
4387 rsurface.lightmapcolor4f = rsurface.array_color4f;
4388 rsurface.lightmapcolor4f_bufferobject = 0;
4389 rsurface.lightmapcolor4f_bufferoffset = 0;
4392 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4394 int texturesurfaceindex;
4397 if (!rsurface.lightmapcolor4f)
4399 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4401 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4402 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)
4410 rsurface.lightmapcolor4f = rsurface.array_color4f;
4411 rsurface.lightmapcolor4f_bufferobject = 0;
4412 rsurface.lightmapcolor4f_bufferoffset = 0;
4415 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4418 rsurface.lightmapcolor4f = NULL;
4419 rsurface.lightmapcolor4f_bufferobject = 0;
4420 rsurface.lightmapcolor4f_bufferoffset = 0;
4421 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4422 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4423 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4424 GL_Color(r, g, b, a);
4425 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4428 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4430 // TODO: optimize applyfog && applycolor case
4431 // just apply fog if necessary, and tint the fog color array if necessary
4432 rsurface.lightmapcolor4f = NULL;
4433 rsurface.lightmapcolor4f_bufferobject = 0;
4434 rsurface.lightmapcolor4f_bufferoffset = 0;
4435 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4436 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4437 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4438 GL_Color(r, g, b, a);
4439 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4442 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4444 int texturesurfaceindex;
4448 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4450 // generate color arrays for the surfaces in this list
4451 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4453 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4454 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4456 if (surface->lightmapinfo->samples)
4458 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4459 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4460 VectorScale(lm, scale, c);
4461 if (surface->lightmapinfo->styles[1] != 255)
4463 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4465 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4466 VectorMA(c, scale, lm, c);
4467 if (surface->lightmapinfo->styles[2] != 255)
4470 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4471 VectorMA(c, scale, lm, c);
4472 if (surface->lightmapinfo->styles[3] != 255)
4475 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4476 VectorMA(c, scale, lm, c);
4486 rsurface.lightmapcolor4f = rsurface.array_color4f;
4487 rsurface.lightmapcolor4f_bufferobject = 0;
4488 rsurface.lightmapcolor4f_bufferoffset = 0;
4492 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4493 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4494 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4496 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4497 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4498 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4499 GL_Color(r, g, b, a);
4500 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4503 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4505 int texturesurfaceindex;
4509 vec3_t ambientcolor;
4510 vec3_t diffusecolor;
4514 VectorCopy(rsurface.modellight_lightdir, lightdir);
4515 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4516 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4517 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4518 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4519 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4520 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4521 if (VectorLength2(diffusecolor) > 0)
4523 // generate color arrays for the surfaces in this list
4524 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4526 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4527 int numverts = surface->num_vertices;
4528 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4529 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4530 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4531 // q3-style directional shading
4532 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4534 if ((f = DotProduct(c2, lightdir)) > 0)
4535 VectorMA(ambientcolor, f, diffusecolor, c);
4537 VectorCopy(ambientcolor, c);
4546 rsurface.lightmapcolor4f = rsurface.array_color4f;
4547 rsurface.lightmapcolor4f_bufferobject = 0;
4548 rsurface.lightmapcolor4f_bufferoffset = 0;
4552 r = ambientcolor[0];
4553 g = ambientcolor[1];
4554 b = ambientcolor[2];
4555 rsurface.lightmapcolor4f = NULL;
4556 rsurface.lightmapcolor4f_bufferobject = 0;
4557 rsurface.lightmapcolor4f_bufferoffset = 0;
4559 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4560 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4561 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4562 GL_Color(r, g, b, a);
4563 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4566 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4568 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4569 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4570 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4571 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4572 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4574 rsurface.mode = RSURFMODE_SHOWSURFACES;
4576 GL_BlendFunc(GL_ONE, GL_ZERO);
4577 R_Mesh_ColorPointer(NULL, 0, 0);
4578 R_Mesh_ResetTextureState();
4580 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4581 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4584 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4586 // transparent sky would be ridiculous
4587 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4589 if (rsurface.mode != RSURFMODE_SKY)
4591 if (rsurface.mode == RSURFMODE_GLSL)
4593 qglUseProgramObjectARB(0);CHECKGLERROR
4595 rsurface.mode = RSURFMODE_SKY;
4599 skyrendernow = false;
4601 // restore entity matrix
4602 R_Mesh_Matrix(&rsurface.matrix);
4604 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4605 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4606 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4607 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4609 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4610 // skymasking on them, and Quake3 never did sky masking (unlike
4611 // software Quake and software Quake2), so disable the sky masking
4612 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4613 // and skymasking also looks very bad when noclipping outside the
4614 // level, so don't use it then either.
4615 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4617 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4618 R_Mesh_ColorPointer(NULL, 0, 0);
4619 R_Mesh_ResetTextureState();
4620 if (skyrendermasked)
4622 // depth-only (masking)
4623 GL_ColorMask(0,0,0,0);
4624 // just to make sure that braindead drivers don't draw
4625 // anything despite that colormask...
4626 GL_BlendFunc(GL_ZERO, GL_ONE);
4631 GL_BlendFunc(GL_ONE, GL_ZERO);
4633 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4634 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4635 if (skyrendermasked)
4636 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4640 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4642 if (rsurface.mode != RSURFMODE_GLSL)
4644 rsurface.mode = RSURFMODE_GLSL;
4645 R_Mesh_ResetTextureState();
4648 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4649 if (!r_glsl_permutation)
4652 if (rsurface.lightmode == 2)
4653 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4655 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4656 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4657 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4658 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4659 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4660 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4662 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]);
4663 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4665 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4666 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4667 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4668 R_Mesh_ColorPointer(NULL, 0, 0);
4670 else if (rsurface.uselightmaptexture)
4672 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4673 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4674 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4675 R_Mesh_ColorPointer(NULL, 0, 0);
4679 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4680 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4681 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4682 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4685 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4686 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4688 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4689 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4694 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4696 // OpenGL 1.3 path - anything not completely ancient
4697 int texturesurfaceindex;
4698 qboolean applycolor;
4702 const texturelayer_t *layer;
4703 if (rsurface.mode != RSURFMODE_MULTIPASS)
4704 rsurface.mode = RSURFMODE_MULTIPASS;
4705 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4706 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4709 int layertexrgbscale;
4710 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4712 if (layerindex == 0)
4716 GL_AlphaTest(false);
4717 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4720 GL_DepthMask(layer->depthmask);
4721 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4722 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4724 layertexrgbscale = 4;
4725 VectorScale(layer->color, 0.25f, layercolor);
4727 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4729 layertexrgbscale = 2;
4730 VectorScale(layer->color, 0.5f, layercolor);
4734 layertexrgbscale = 1;
4735 VectorScale(layer->color, 1.0f, layercolor);
4737 layercolor[3] = layer->color[3];
4738 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4739 R_Mesh_ColorPointer(NULL, 0, 0);
4740 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4741 switch (layer->type)
4743 case TEXTURELAYERTYPE_LITTEXTURE:
4744 memset(&m, 0, sizeof(m));
4745 m.tex[0] = R_GetTexture(r_texture_white);
4746 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4747 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4748 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4749 m.tex[1] = R_GetTexture(layer->texture);
4750 m.texmatrix[1] = layer->texmatrix;
4751 m.texrgbscale[1] = layertexrgbscale;
4752 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4753 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4754 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4755 R_Mesh_TextureState(&m);
4756 if (rsurface.lightmode == 2)
4757 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4758 else if (rsurface.uselightmaptexture)
4759 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4761 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4763 case TEXTURELAYERTYPE_TEXTURE:
4764 memset(&m, 0, sizeof(m));
4765 m.tex[0] = R_GetTexture(layer->texture);
4766 m.texmatrix[0] = layer->texmatrix;
4767 m.texrgbscale[0] = layertexrgbscale;
4768 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4769 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4770 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4771 R_Mesh_TextureState(&m);
4772 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4774 case TEXTURELAYERTYPE_FOG:
4775 memset(&m, 0, sizeof(m));
4776 m.texrgbscale[0] = layertexrgbscale;
4779 m.tex[0] = R_GetTexture(layer->texture);
4780 m.texmatrix[0] = layer->texmatrix;
4781 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4782 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4783 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4785 R_Mesh_TextureState(&m);
4786 // generate a color array for the fog pass
4787 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4788 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4792 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4793 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)
4795 f = 1 - FogPoint_Model(v);
4796 c[0] = layercolor[0];
4797 c[1] = layercolor[1];
4798 c[2] = layercolor[2];
4799 c[3] = f * layercolor[3];
4802 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4805 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4807 GL_LockArrays(0, 0);
4810 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4812 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4813 GL_AlphaTest(false);
4817 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4819 // OpenGL 1.1 - crusty old voodoo path
4820 int texturesurfaceindex;
4824 const texturelayer_t *layer;
4825 if (rsurface.mode != RSURFMODE_MULTIPASS)
4826 rsurface.mode = RSURFMODE_MULTIPASS;
4827 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4828 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4830 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4832 if (layerindex == 0)
4836 GL_AlphaTest(false);
4837 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4840 GL_DepthMask(layer->depthmask);
4841 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4842 R_Mesh_ColorPointer(NULL, 0, 0);
4843 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4844 switch (layer->type)
4846 case TEXTURELAYERTYPE_LITTEXTURE:
4847 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4849 // two-pass lit texture with 2x rgbscale
4850 // first the lightmap pass
4851 memset(&m, 0, sizeof(m));
4852 m.tex[0] = R_GetTexture(r_texture_white);
4853 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4854 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4855 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4856 R_Mesh_TextureState(&m);
4857 if (rsurface.lightmode == 2)
4858 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4859 else if (rsurface.uselightmaptexture)
4860 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4862 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4863 GL_LockArrays(0, 0);
4864 // then apply the texture to it
4865 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4866 memset(&m, 0, sizeof(m));
4867 m.tex[0] = R_GetTexture(layer->texture);
4868 m.texmatrix[0] = layer->texmatrix;
4869 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4870 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4871 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4872 R_Mesh_TextureState(&m);
4873 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);
4877 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4878 memset(&m, 0, sizeof(m));
4879 m.tex[0] = R_GetTexture(layer->texture);
4880 m.texmatrix[0] = layer->texmatrix;
4881 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4882 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4883 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4884 R_Mesh_TextureState(&m);
4885 if (rsurface.lightmode == 2)
4886 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);
4888 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);
4891 case TEXTURELAYERTYPE_TEXTURE:
4892 // singletexture unlit texture with transparency support
4893 memset(&m, 0, sizeof(m));
4894 m.tex[0] = R_GetTexture(layer->texture);
4895 m.texmatrix[0] = layer->texmatrix;
4896 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4897 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4898 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4899 R_Mesh_TextureState(&m);
4900 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);
4902 case TEXTURELAYERTYPE_FOG:
4903 // singletexture fogging
4904 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4907 memset(&m, 0, sizeof(m));
4908 m.tex[0] = R_GetTexture(layer->texture);
4909 m.texmatrix[0] = layer->texmatrix;
4910 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4911 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4912 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4913 R_Mesh_TextureState(&m);
4916 R_Mesh_ResetTextureState();
4917 // generate a color array for the fog pass
4918 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4922 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4923 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)
4925 f = 1 - FogPoint_Model(v);
4926 c[0] = layer->color[0];
4927 c[1] = layer->color[1];
4928 c[2] = layer->color[2];
4929 c[3] = f * layer->color[3];
4932 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4935 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4937 GL_LockArrays(0, 0);
4940 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4942 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4943 GL_AlphaTest(false);
4947 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4949 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4951 rsurface.rtlight = NULL;
4955 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4957 if (rsurface.mode != RSURFMODE_MULTIPASS)
4958 rsurface.mode = RSURFMODE_MULTIPASS;
4959 if (r_depthfirst.integer == 3)
4961 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4962 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4966 GL_ColorMask(0,0,0,0);
4969 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4970 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4971 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4973 GL_BlendFunc(GL_ONE, GL_ZERO);
4975 GL_AlphaTest(false);
4976 R_Mesh_ColorPointer(NULL, 0, 0);
4977 R_Mesh_ResetTextureState();
4978 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4979 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4980 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4981 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4983 else if (r_depthfirst.integer == 3)
4985 else if (r_showsurfaces.integer)
4987 if (rsurface.mode != RSURFMODE_MULTIPASS)
4988 rsurface.mode = RSURFMODE_MULTIPASS;
4989 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4990 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4992 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4993 GL_BlendFunc(GL_ONE, GL_ZERO);
4994 GL_DepthMask(writedepth);
4996 GL_AlphaTest(false);
4997 R_Mesh_ColorPointer(NULL, 0, 0);
4998 R_Mesh_ResetTextureState();
4999 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5000 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5001 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5003 else if (gl_lightmaps.integer)
5006 if (rsurface.mode != RSURFMODE_MULTIPASS)
5007 rsurface.mode = RSURFMODE_MULTIPASS;
5008 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5010 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5011 GL_BlendFunc(GL_ONE, GL_ZERO);
5012 GL_DepthMask(writedepth);
5014 GL_AlphaTest(false);
5015 R_Mesh_ColorPointer(NULL, 0, 0);
5016 memset(&m, 0, sizeof(m));
5017 m.tex[0] = R_GetTexture(r_texture_white);
5018 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5019 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5020 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5021 R_Mesh_TextureState(&m);
5022 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5023 if (rsurface.lightmode == 2)
5024 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5025 else if (rsurface.uselightmaptexture)
5026 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5028 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5029 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5031 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5033 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5034 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5036 else if (rsurface.texture->currentnumlayers)
5038 // write depth for anything we skipped on the depth-only pass earlier
5039 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5041 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5042 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5043 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5044 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5045 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5046 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5047 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5048 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5049 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5050 if (r_glsl.integer && gl_support_fragment_shader)
5051 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5052 else if (gl_combine.integer && r_textureunits.integer >= 2)
5053 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5055 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5056 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5059 GL_LockArrays(0, 0);
5062 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5065 int texturenumsurfaces, endsurface;
5067 msurface_t *surface;
5068 msurface_t *texturesurfacelist[1024];
5070 // if the model is static it doesn't matter what value we give for
5071 // wantnormals and wanttangents, so this logic uses only rules applicable
5072 // to a model, knowing that they are meaningless otherwise
5073 if (ent == r_refdef.worldentity)
5074 RSurf_ActiveWorldEntity();
5075 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5076 RSurf_ActiveModelEntity(ent, false, false);
5078 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5080 for (i = 0;i < numsurfaces;i = j)
5083 surface = rsurface.modelsurfaces + surfacelist[i];
5084 texture = surface->texture;
5085 R_UpdateTextureInfo(ent, texture);
5086 rsurface.texture = texture->currentframe;
5087 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5088 // scan ahead until we find a different texture
5089 endsurface = min(i + 1024, numsurfaces);
5090 texturenumsurfaces = 0;
5091 texturesurfacelist[texturenumsurfaces++] = surface;
5092 for (;j < endsurface;j++)
5094 surface = rsurface.modelsurfaces + surfacelist[j];
5095 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5097 texturesurfacelist[texturenumsurfaces++] = surface;
5099 // render the range of surfaces
5100 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5106 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5109 vec3_t tempcenter, center;
5111 // break the surface list down into batches by texture and use of lightmapping
5112 for (i = 0;i < numsurfaces;i = j)
5115 // texture is the base texture pointer, rsurface.texture is the
5116 // current frame/skin the texture is directing us to use (for example
5117 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5118 // use skin 1 instead)
5119 texture = surfacelist[i]->texture;
5120 rsurface.texture = texture->currentframe;
5121 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5122 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5124 // if this texture is not the kind we want, skip ahead to the next one
5125 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5129 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5131 // transparent surfaces get pushed off into the transparent queue
5132 const msurface_t *surface = surfacelist[i];
5135 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5136 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5137 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5138 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5139 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5143 // simply scan ahead until we find a different texture or lightmap state
5144 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5146 // render the range of surfaces
5147 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5152 float locboxvertex3f[6*4*3] =
5154 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5155 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5156 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5157 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5158 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5159 1,0,0, 0,0,0, 0,1,0, 1,1,0
5162 int locboxelement3i[6*2*3] =
5172 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5175 cl_locnode_t *loc = (cl_locnode_t *)ent;
5177 float vertex3f[6*4*3];
5179 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5180 GL_DepthMask(false);
5181 GL_DepthRange(0, 1);
5182 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5184 GL_CullFace(GL_NONE);
5185 R_Mesh_Matrix(&identitymatrix);
5187 R_Mesh_VertexPointer(vertex3f, 0, 0);
5188 R_Mesh_ColorPointer(NULL, 0, 0);
5189 R_Mesh_ResetTextureState();
5192 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5193 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5194 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5195 surfacelist[0] < 0 ? 0.5f : 0.125f);
5197 if (VectorCompare(loc->mins, loc->maxs))
5199 VectorSet(size, 2, 2, 2);
5200 VectorMA(loc->mins, -0.5f, size, mins);
5204 VectorCopy(loc->mins, mins);
5205 VectorSubtract(loc->maxs, loc->mins, size);
5208 for (i = 0;i < 6*4*3;)
5209 for (j = 0;j < 3;j++, i++)
5210 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5212 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5215 void R_DrawLocs(void)
5218 cl_locnode_t *loc, *nearestloc;
5220 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5221 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5223 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5224 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5228 void R_DrawCollisionBrushes(entity_render_t *ent)
5232 msurface_t *surface;
5233 model_t *model = ent->model;
5234 if (!model->brush.num_brushes)
5237 R_Mesh_ColorPointer(NULL, 0, 0);
5238 R_Mesh_ResetTextureState();
5239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5240 GL_DepthMask(false);
5241 GL_DepthRange(0, 1);
5242 GL_DepthTest(!r_showdisabledepthtest.integer);
5243 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5244 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5245 if (brush->colbrushf && brush->colbrushf->numtriangles)
5246 R_DrawCollisionBrush(brush->colbrushf);
5247 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5248 if (surface->num_collisiontriangles)
5249 R_DrawCollisionSurface(ent, surface);
5250 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5253 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5256 const int *elements;
5257 msurface_t *surface;
5258 model_t *model = ent->model;
5261 GL_DepthRange(0, 1);
5262 GL_DepthTest(!r_showdisabledepthtest.integer);
5263 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5265 GL_BlendFunc(GL_ONE, GL_ZERO);
5266 R_Mesh_ColorPointer(NULL, 0, 0);
5267 R_Mesh_ResetTextureState();
5268 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5270 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5272 rsurface.texture = surface->texture->currentframe;
5273 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5275 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5278 if (!rsurface.texture->currentlayers->depthmask)
5279 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5280 else if (ent == r_refdef.worldentity)
5281 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5283 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5284 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5287 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5289 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5290 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5291 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5292 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5299 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5303 VectorCopy(rsurface.vertex3f + l * 3, v);
5304 qglVertex3f(v[0], v[1], v[2]);
5305 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5306 qglVertex3f(v[0], v[1], v[2]);
5310 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5312 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5314 VectorCopy(rsurface.vertex3f + l * 3, v);
5315 qglVertex3f(v[0], v[1], v[2]);
5316 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5317 qglVertex3f(v[0], v[1], v[2]);
5321 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5323 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5325 VectorCopy(rsurface.vertex3f + l * 3, v);
5326 qglVertex3f(v[0], v[1], v[2]);
5327 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5328 qglVertex3f(v[0], v[1], v[2]);
5335 rsurface.texture = NULL;
5338 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5339 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5341 int i, j, endj, f, flagsmask;
5342 int counttriangles = 0;
5343 msurface_t *surface, **surfacechain;
5345 model_t *model = r_refdef.worldmodel;
5346 const int maxsurfacelist = 1024;
5347 int numsurfacelist = 0;
5348 msurface_t *surfacelist[1024];
5352 RSurf_ActiveWorldEntity();
5354 // update light styles
5355 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5357 for (i = 0;i < model->brushq1.light_styles;i++)
5359 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5361 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5362 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5363 for (;(surface = *surfacechain);surfacechain++)
5364 surface->cached_dlight = true;
5369 R_UpdateAllTextureInfo(r_refdef.worldentity);
5370 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5373 rsurface.uselightmaptexture = false;
5374 rsurface.texture = NULL;
5376 j = model->firstmodelsurface;
5377 endj = j + model->nummodelsurfaces;
5380 // quickly skip over non-visible surfaces
5381 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5383 // quickly iterate over visible surfaces
5384 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5386 // process this surface
5387 surface = model->data_surfaces + j;
5388 // if this surface fits the criteria, add it to the list
5389 if (surface->num_triangles)
5391 // if lightmap parameters changed, rebuild lightmap texture
5392 if (surface->cached_dlight)
5393 R_BuildLightMap(r_refdef.worldentity, surface);
5394 // add face to draw list
5395 surfacelist[numsurfacelist++] = surface;
5396 counttriangles += surface->num_triangles;
5397 if (numsurfacelist >= maxsurfacelist)
5399 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5406 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5407 r_refdef.stats.entities_triangles += counttriangles;
5410 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5411 R_DrawCollisionBrushes(r_refdef.worldentity);
5413 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5414 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5417 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5419 int i, f, flagsmask;
5420 int counttriangles = 0;
5421 msurface_t *surface, *endsurface, **surfacechain;
5423 model_t *model = ent->model;
5424 const int maxsurfacelist = 1024;
5425 int numsurfacelist = 0;
5426 msurface_t *surfacelist[1024];
5430 // if the model is static it doesn't matter what value we give for
5431 // wantnormals and wanttangents, so this logic uses only rules applicable
5432 // to a model, knowing that they are meaningless otherwise
5433 if (ent == r_refdef.worldentity)
5434 RSurf_ActiveWorldEntity();
5435 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5436 RSurf_ActiveModelEntity(ent, false, false);
5438 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5440 // update light styles
5441 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5443 for (i = 0;i < model->brushq1.light_styles;i++)
5445 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5447 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5448 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5449 for (;(surface = *surfacechain);surfacechain++)
5450 surface->cached_dlight = true;
5455 R_UpdateAllTextureInfo(ent);
5456 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5459 rsurface.uselightmaptexture = false;
5460 rsurface.texture = NULL;
5462 surface = model->data_surfaces + model->firstmodelsurface;
5463 endsurface = surface + model->nummodelsurfaces;
5464 for (;surface < endsurface;surface++)
5466 // if this surface fits the criteria, add it to the list
5467 if (surface->num_triangles)
5469 // if lightmap parameters changed, rebuild lightmap texture
5470 if (surface->cached_dlight)
5471 R_BuildLightMap(ent, surface);
5472 // add face to draw list
5473 surfacelist[numsurfacelist++] = surface;
5474 counttriangles += surface->num_triangles;
5475 if (numsurfacelist >= maxsurfacelist)
5477 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5483 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5484 r_refdef.stats.entities_triangles += counttriangles;
5487 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5488 R_DrawCollisionBrushes(ent);
5490 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5491 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);