2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
85 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
86 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
88 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
89 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
90 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
91 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
92 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
93 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
94 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
96 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
97 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
98 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
99 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
101 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
103 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
105 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
107 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
108 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
110 extern qboolean v_flipped_state;
112 typedef struct r_glsl_bloomshader_s
115 int loc_Texture_Bloom;
117 r_glsl_bloomshader_t;
119 static struct r_bloomstate_s
124 int bloomwidth, bloomheight;
126 int screentexturewidth, screentextureheight;
127 rtexture_t *texture_screen;
129 int bloomtexturewidth, bloomtextureheight;
130 rtexture_t *texture_bloom;
132 r_glsl_bloomshader_t *shader;
134 // arrays for rendering the screen passes
135 float screentexcoord2f[8];
136 float bloomtexcoord2f[8];
137 float offsettexcoord2f[8];
141 // shadow volume bsp struct with automatically growing nodes buffer
144 rtexture_t *r_texture_blanknormalmap;
145 rtexture_t *r_texture_white;
146 rtexture_t *r_texture_black;
147 rtexture_t *r_texture_notexture;
148 rtexture_t *r_texture_whitecube;
149 rtexture_t *r_texture_normalizationcube;
150 rtexture_t *r_texture_fogattenuation;
151 //rtexture_t *r_texture_fogintensity;
153 // information about each possible shader permutation
154 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
155 // currently selected permutation
156 r_glsl_permutation_t *r_glsl_permutation;
158 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
159 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
161 // vertex coordinates for a quad that covers the screen exactly
162 const static float r_screenvertex3f[12] =
170 extern void R_DrawModelShadows(void);
172 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
175 for (i = 0;i < verts;i++)
186 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
189 for (i = 0;i < verts;i++)
199 // FIXME: move this to client?
202 if (gamemode == GAME_NEHAHRA)
204 Cvar_Set("gl_fogenable", "0");
205 Cvar_Set("gl_fogdensity", "0.2");
206 Cvar_Set("gl_fogred", "0.3");
207 Cvar_Set("gl_foggreen", "0.3");
208 Cvar_Set("gl_fogblue", "0.3");
210 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
213 float FogPoint_World(const vec3_t p)
215 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
216 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
219 float FogPoint_Model(const vec3_t p)
221 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
222 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
225 static void R_BuildBlankTextures(void)
227 unsigned char data[4];
228 data[0] = 128; // normal X
229 data[1] = 128; // normal Y
230 data[2] = 255; // normal Z
231 data[3] = 128; // height
232 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
237 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
242 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 static void R_BuildNoTexture(void)
248 unsigned char pix[16][16][4];
249 // this makes a light grey/dark grey checkerboard texture
250 for (y = 0;y < 16;y++)
252 for (x = 0;x < 16;x++)
254 if ((y < 8) ^ (x < 8))
270 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
273 static void R_BuildWhiteCube(void)
275 unsigned char data[6*1*1*4];
276 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
277 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
278 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
279 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
280 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
281 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
282 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
285 static void R_BuildNormalizationCube(void)
289 vec_t s, t, intensity;
291 unsigned char data[6][NORMSIZE][NORMSIZE][4];
292 for (side = 0;side < 6;side++)
294 for (y = 0;y < NORMSIZE;y++)
296 for (x = 0;x < NORMSIZE;x++)
298 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
299 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
334 intensity = 127.0f / sqrt(DotProduct(v, v));
335 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
336 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
337 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
338 data[side][y][x][3] = 255;
342 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
345 static void R_BuildFogTexture(void)
349 unsigned char data1[FOGWIDTH][4];
350 //unsigned char data2[FOGWIDTH][4];
351 for (x = 0;x < FOGWIDTH;x++)
353 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
358 //data2[x][0] = 255 - b;
359 //data2[x][1] = 255 - b;
360 //data2[x][2] = 255 - b;
363 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
364 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
367 static const char *builtinshaderstring =
368 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
369 "// written by Forest 'LordHavoc' Hale\n"
371 "// common definitions between vertex shader and fragment shader:\n"
373 "#ifdef __GLSL_CG_DATA_TYPES\n"
374 "#define myhalf half\n"
375 "#define myhvec2 hvec2\n"
376 "#define myhvec3 hvec3\n"
377 "#define myhvec4 hvec4\n"
379 "#define myhalf float\n"
380 "#define myhvec2 vec2\n"
381 "#define myhvec3 vec3\n"
382 "#define myhvec4 vec4\n"
385 "varying vec2 TexCoord;\n"
386 "varying vec2 TexCoordLightmap;\n"
388 "varying vec3 CubeVector;\n"
389 "varying vec3 LightVector;\n"
390 "varying vec3 EyeVector;\n"
392 "varying vec3 EyeVectorModelSpace;\n"
395 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
396 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
397 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
402 "// vertex shader specific:\n"
403 "#ifdef VERTEX_SHADER\n"
405 "uniform vec3 LightPosition;\n"
406 "uniform vec3 EyePosition;\n"
407 "uniform vec3 LightDir;\n"
409 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
413 " gl_FrontColor = gl_Color;\n"
414 " // copy the surface texcoord\n"
415 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
416 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
417 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
420 "#ifdef MODE_LIGHTSOURCE\n"
421 " // transform vertex position into light attenuation/cubemap space\n"
422 " // (-1 to +1 across the light box)\n"
423 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
425 " // transform unnormalized light direction into tangent space\n"
426 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
427 " // normalize it per pixel)\n"
428 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
429 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
430 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
431 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
434 "#ifdef MODE_LIGHTDIRECTION\n"
435 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
436 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
437 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
440 " // transform unnormalized eye direction into tangent space\n"
442 " vec3 EyeVectorModelSpace;\n"
444 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
445 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
446 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
447 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
449 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
450 " VectorS = gl_MultiTexCoord1.xyz;\n"
451 " VectorT = gl_MultiTexCoord2.xyz;\n"
452 " VectorR = gl_MultiTexCoord3.xyz;\n"
455 " // transform vertex to camera space, using ftransform to match non-VS\n"
457 " gl_Position = ftransform();\n"
460 "#endif // VERTEX_SHADER\n"
465 "// fragment shader specific:\n"
466 "#ifdef FRAGMENT_SHADER\n"
468 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
469 "uniform sampler2D Texture_Normal;\n"
470 "uniform sampler2D Texture_Color;\n"
471 "uniform sampler2D Texture_Gloss;\n"
472 "uniform samplerCube Texture_Cube;\n"
473 "uniform sampler2D Texture_Attenuation;\n"
474 "uniform sampler2D Texture_FogMask;\n"
475 "uniform sampler2D Texture_Pants;\n"
476 "uniform sampler2D Texture_Shirt;\n"
477 "uniform sampler2D Texture_Lightmap;\n"
478 "uniform sampler2D Texture_Deluxemap;\n"
479 "uniform sampler2D Texture_Glow;\n"
481 "uniform myhvec3 LightColor;\n"
482 "uniform myhvec3 AmbientColor;\n"
483 "uniform myhvec3 DiffuseColor;\n"
484 "uniform myhvec3 SpecularColor;\n"
485 "uniform myhvec3 Color_Pants;\n"
486 "uniform myhvec3 Color_Shirt;\n"
487 "uniform myhvec3 FogColor;\n"
489 "uniform myhalf GlowScale;\n"
490 "uniform myhalf SceneBrightness;\n"
491 "#ifdef USECONTRASTBOOST\n"
492 "uniform myhalf ContrastBoostCoeff;\n"
495 "uniform float OffsetMapping_Scale;\n"
496 "uniform float OffsetMapping_Bias;\n"
497 "uniform float FogRangeRecip;\n"
499 "uniform myhalf AmbientScale;\n"
500 "uniform myhalf DiffuseScale;\n"
501 "uniform myhalf SpecularScale;\n"
502 "uniform myhalf SpecularPower;\n"
504 "#ifdef USEOFFSETMAPPING\n"
505 "vec2 OffsetMapping(vec2 TexCoord)\n"
507 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
508 " // 14 sample relief mapping: linear search and then binary search\n"
509 " // this basically steps forward a small amount repeatedly until it finds\n"
510 " // itself inside solid, then jitters forward and back using decreasing\n"
511 " // amounts to find the impact\n"
512 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
513 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
514 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
515 " vec3 RT = vec3(TexCoord, 1);\n"
516 " OffsetVector *= 0.1;\n"
517 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
518 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
519 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
520 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
521 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
522 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
523 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
524 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
525 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
526 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
527 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
528 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
529 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
530 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
533 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
534 " // this basically moves forward the full distance, and then backs up based\n"
535 " // on height of samples\n"
536 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
537 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
538 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
539 " TexCoord += OffsetVector;\n"
540 " OffsetVector *= 0.333;\n"
541 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
542 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " return TexCoord;\n"
551 "#ifdef USEOFFSETMAPPING\n"
552 " // apply offsetmapping\n"
553 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
554 "#define TexCoord TexCoordOffset\n"
557 " // combine the diffuse textures (base, pants, shirt)\n"
558 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
559 "#ifdef USECOLORMAPPING\n"
560 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
566 "#ifdef MODE_LIGHTSOURCE\n"
569 " // calculate surface normal, light normal, and specular normal\n"
570 " // compute color intensity for the two textures (colormap and glossmap)\n"
571 " // scale by light color and attenuation as efficiently as possible\n"
572 " // (do as much scalar math as possible rather than vector math)\n"
573 "#ifdef USESPECULAR\n"
574 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
575 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
576 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
578 " // calculate directional shading\n"
579 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
581 "#ifdef USEDIFFUSE\n"
582 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
583 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
585 " // calculate directional shading\n"
586 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
588 " // calculate directionless shading\n"
589 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
593 "#ifdef USECUBEFILTER\n"
594 " // apply light cubemap filter\n"
595 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
596 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
602 "#elif defined(MODE_LIGHTDIRECTION)\n"
603 " // directional model lighting\n"
605 " // get the surface normal and light normal\n"
606 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
607 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
609 " // calculate directional shading\n"
610 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
611 "#ifdef USESPECULAR\n"
612 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
613 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
619 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
620 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
622 " // get the surface normal and light normal\n"
623 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
625 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
626 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
627 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
629 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
631 " // calculate directional shading\n"
632 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
633 "#ifdef USESPECULAR\n"
634 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
635 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
638 " // apply lightmap color\n"
639 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
642 "#else // MODE none (lightmap)\n"
643 " // apply lightmap color\n"
644 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
647 " color *= myhvec4(gl_Color);\n"
650 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
655 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
658 "#ifdef USECONTRASTBOOST\n"
659 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
661 " color.rgb *= SceneBrightness;\n"
664 " gl_FragColor = vec4(color);\n"
667 "#endif // FRAGMENT_SHADER\n"
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 const char *permutationinfo[][2] =
673 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
674 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
677 {"#define USEGLOW\n", " glow"},
678 {"#define USEFOG\n", " fog"},
679 {"#define USECOLORMAPPING\n", " colormapping"},
680 {"#define USEDIFFUSE\n", " diffuse"},
681 {"#define USECONTRASTBOOST\n", " contrastboost"},
682 {"#define USESPECULAR\n", " specular"},
683 {"#define USECUBEFILTER\n", " cubefilter"},
684 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
685 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
689 void R_GLSL_CompilePermutation(const char *filename, int permutation)
692 qboolean shaderfound;
693 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
694 int vertstrings_count;
695 int geomstrings_count;
696 int fragstrings_count;
698 const char *vertstrings_list[32+1];
699 const char *geomstrings_list[32+1];
700 const char *fragstrings_list[32+1];
701 char permutationname[256];
706 vertstrings_list[0] = "#define VERTEX_SHADER\n";
707 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
708 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
709 vertstrings_count = 1;
710 geomstrings_count = 1;
711 fragstrings_count = 1;
712 permutationname[0] = 0;
713 for (i = 0;permutationinfo[i][0];i++)
715 if (permutation & (1<<i))
717 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
718 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
719 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
720 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
724 // keep line numbers correct
725 vertstrings_list[vertstrings_count++] = "\n";
726 geomstrings_list[geomstrings_count++] = "\n";
727 fragstrings_list[fragstrings_count++] = "\n";
730 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
734 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
735 vertstrings_list[vertstrings_count++] = shaderstring;
736 geomstrings_list[geomstrings_count++] = shaderstring;
737 fragstrings_list[fragstrings_count++] = shaderstring;
740 else if (!strcmp(filename, "glsl/default.glsl"))
742 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
743 vertstrings_list[vertstrings_count++] = builtinshaderstring;
744 geomstrings_list[geomstrings_count++] = builtinshaderstring;
745 fragstrings_list[fragstrings_count++] = builtinshaderstring;
748 // clear any lists that are not needed by this shader
749 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
750 vertstrings_count = 0;
751 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
752 geomstrings_count = 0;
753 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
754 fragstrings_count = 0;
755 // compile the shader program
756 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
757 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
761 qglUseProgramObjectARB(p->program);CHECKGLERROR
762 // look up all the uniform variable names we care about, so we don't
763 // have to look them up every time we set them
764 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
765 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
766 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
767 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
768 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
769 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
770 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
771 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
772 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
773 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
774 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
775 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
776 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
777 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
778 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
779 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
780 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
781 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
782 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
783 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
784 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
785 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
786 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
787 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
788 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
789 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
790 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
791 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
792 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
793 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
794 // initialize the samplers to refer to the texture units we use
795 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
796 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
797 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
798 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
799 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
800 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
801 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
802 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
803 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
804 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
805 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
807 qglUseProgramObjectARB(0);CHECKGLERROR
810 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
812 Mem_Free(shaderstring);
815 void R_GLSL_Restart_f(void)
818 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
819 if (r_glsl_permutations[i].program)
820 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
821 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
824 void R_GLSL_DumpShader_f(void)
828 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
831 Con_Printf("failed to write to glsl/default.glsl\n");
835 FS_Print(file, "// The engine may define the following macros:\n");
836 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
837 for (i = 0;permutationinfo[i][0];i++)
838 FS_Printf(file, "// %s", permutationinfo[i][0]);
839 FS_Print(file, "\n");
840 FS_Print(file, builtinshaderstring);
843 Con_Printf("data/default.glsl written\n");
846 extern rtexture_t *r_shadow_attenuationgradienttexture;
847 extern rtexture_t *r_shadow_attenuation2dtexture;
848 extern rtexture_t *r_shadow_attenuation3dtexture;
849 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
851 // select a permutation of the lighting shader appropriate to this
852 // combination of texture, entity, light source, and fogging, only use the
853 // minimum features necessary to avoid wasting rendering time in the
854 // fragment shader on features that are not being used
855 const char *shaderfilename = NULL;
856 unsigned int permutation = 0;
858 r_glsl_permutation = NULL;
859 // TODO: implement geometry-shader based shadow volumes someday
860 if (rsurface.rtlight)
863 shaderfilename = "glsl/default.glsl";
864 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
865 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
866 permutation |= SHADERPERMUTATION_CUBEFILTER;
867 if (diffusescale > 0)
868 permutation |= SHADERPERMUTATION_DIFFUSE;
869 if (specularscale > 0)
870 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
871 if (r_refdef.fogenabled)
872 permutation |= SHADERPERMUTATION_FOG;
873 if (rsurface.texture->colormapping)
874 permutation |= SHADERPERMUTATION_COLORMAPPING;
875 if (r_glsl_offsetmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
878 if (r_glsl_offsetmapping_reliefmapping.integer)
879 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
881 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
882 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
884 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
886 // bright unshaded geometry
887 shaderfilename = "glsl/default.glsl";
888 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
889 if (rsurface.texture->currentskinframe->glow)
890 permutation |= SHADERPERMUTATION_GLOW;
891 if (r_refdef.fogenabled)
892 permutation |= SHADERPERMUTATION_FOG;
893 if (rsurface.texture->colormapping)
894 permutation |= SHADERPERMUTATION_COLORMAPPING;
895 if (r_glsl_offsetmapping.integer)
897 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
898 if (r_glsl_offsetmapping_reliefmapping.integer)
899 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
901 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
902 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
904 else if (modellighting)
906 // directional model lighting
907 shaderfilename = "glsl/default.glsl";
908 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
909 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
910 if (rsurface.texture->currentskinframe->glow)
911 permutation |= SHADERPERMUTATION_GLOW;
912 if (specularscale > 0)
913 permutation |= SHADERPERMUTATION_SPECULAR;
914 if (r_refdef.fogenabled)
915 permutation |= SHADERPERMUTATION_FOG;
916 if (rsurface.texture->colormapping)
917 permutation |= SHADERPERMUTATION_COLORMAPPING;
918 if (r_glsl_offsetmapping.integer)
920 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
921 if (r_glsl_offsetmapping_reliefmapping.integer)
922 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
924 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
925 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
930 shaderfilename = "glsl/default.glsl";
931 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
932 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
934 // deluxemapping (light direction texture)
935 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
936 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
938 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
939 if (specularscale > 0)
940 permutation |= SHADERPERMUTATION_SPECULAR;
942 else if (r_glsl_deluxemapping.integer >= 2)
944 // fake deluxemapping (uniform light direction in tangentspace)
945 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
946 if (specularscale > 0)
947 permutation |= SHADERPERMUTATION_SPECULAR;
951 // ordinary lightmapping
954 if (rsurface.texture->currentskinframe->glow)
955 permutation |= SHADERPERMUTATION_GLOW;
956 if (r_refdef.fogenabled)
957 permutation |= SHADERPERMUTATION_FOG;
958 if (rsurface.texture->colormapping)
959 permutation |= SHADERPERMUTATION_COLORMAPPING;
960 if (r_glsl_offsetmapping.integer)
962 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
963 if (r_glsl_offsetmapping_reliefmapping.integer)
964 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
966 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
967 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
969 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
971 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
972 R_GLSL_CompilePermutation(shaderfilename, permutation);
973 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
975 // remove features until we find a valid permutation
977 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
980 return 0; // no bit left to clear
981 // reduce i more quickly whenever it would not remove any bits
982 if (!(permutation & i))
985 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
986 R_GLSL_CompilePermutation(shaderfilename, permutation);
987 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
992 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
994 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
995 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
996 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
998 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
999 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1000 if (permutation & SHADERPERMUTATION_DIFFUSE)
1002 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1003 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1004 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1005 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1009 // ambient only is simpler
1010 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1011 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1012 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1013 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1016 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1018 if (r_glsl_permutation->loc_AmbientColor >= 0)
1019 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1020 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1021 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1022 if (r_glsl_permutation->loc_SpecularColor >= 0)
1023 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1024 if (r_glsl_permutation->loc_LightDir >= 0)
1025 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1029 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1030 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1031 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1033 nmap = rsurface.texture->currentskinframe->nmap;
1034 if (gl_lightmaps.integer)
1035 nmap = r_texture_blanknormalmap;
1036 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1037 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1038 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1039 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1040 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1041 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1042 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1043 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1044 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1045 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1046 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1047 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1048 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1050 // The formula used is actually:
1051 // color.rgb *= SceneBrightness;
1052 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1053 // I simplify that to
1054 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1055 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1057 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1058 // and do [[calculations]] here in the engine
1059 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1060 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1063 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1064 if (r_glsl_permutation->loc_FogColor >= 0)
1066 // additive passes are only darkened by fog, not tinted
1067 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1068 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1070 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1072 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1073 if (r_glsl_permutation->loc_Color_Pants >= 0)
1075 if (rsurface.texture->currentskinframe->pants)
1076 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1078 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1080 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1082 if (rsurface.texture->currentskinframe->shirt)
1083 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1085 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1087 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1088 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1089 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1094 void R_SwitchSurfaceShader(int permutation)
1096 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1098 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1100 qglUseProgramObjectARB(r_glsl_permutation->program);
1105 #define SKINFRAME_HASH 1024
1109 int loadsequence; // incremented each level change
1110 memexpandablearray_t array;
1111 skinframe_t *hash[SKINFRAME_HASH];
1115 void R_SkinFrame_PrepareForPurge(void)
1117 r_skinframe.loadsequence++;
1118 // wrap it without hitting zero
1119 if (r_skinframe.loadsequence >= 200)
1120 r_skinframe.loadsequence = 1;
1123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1127 // mark the skinframe as used for the purging code
1128 skinframe->loadsequence = r_skinframe.loadsequence;
1131 void R_SkinFrame_Purge(void)
1135 for (i = 0;i < SKINFRAME_HASH;i++)
1137 for (s = r_skinframe.hash[i];s;s = s->next)
1139 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1141 if (s->base == r_texture_notexture) s->base = NULL;
1142 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1143 if (s->merged == s->base) s->merged = NULL;
1144 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1145 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1146 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1147 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1148 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1149 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1150 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1151 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1152 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1153 s->loadsequence = 0;
1159 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1163 char basename[MAX_QPATH];
1165 Image_StripImageExtension(name, basename, sizeof(basename));
1167 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1168 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1169 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1175 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1176 memset(item, 0, sizeof(*item));
1177 strlcpy(item->basename, basename, sizeof(item->basename));
1178 item->textureflags = textureflags;
1179 item->comparewidth = comparewidth;
1180 item->compareheight = compareheight;
1181 item->comparecrc = comparecrc;
1182 item->next = r_skinframe.hash[hashindex];
1183 r_skinframe.hash[hashindex] = item;
1185 R_SkinFrame_MarkUsed(item);
1189 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1191 // FIXME: it should be possible to disable loading various layers using
1192 // cvars, to prevent wasted loading time and memory usage if the user does
1194 qboolean loadnormalmap = true;
1195 qboolean loadgloss = true;
1196 qboolean loadpantsandshirt = true;
1197 qboolean loadglow = true;
1199 unsigned char *pixels;
1200 unsigned char *bumppixels;
1201 unsigned char *basepixels = NULL;
1202 int basepixels_width;
1203 int basepixels_height;
1204 skinframe_t *skinframe;
1206 if (cls.state == ca_dedicated)
1209 // return an existing skinframe if already loaded
1210 // if loading of the first image fails, don't make a new skinframe as it
1211 // would cause all future lookups of this to be missing
1212 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1213 if (skinframe && skinframe->base)
1216 basepixels = loadimagepixels(name, complain, 0, 0);
1217 if (basepixels == NULL)
1220 // we've got some pixels to store, so really allocate this new texture now
1222 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1223 skinframe->stain = NULL;
1224 skinframe->merged = NULL;
1225 skinframe->base = r_texture_notexture;
1226 skinframe->pants = NULL;
1227 skinframe->shirt = NULL;
1228 skinframe->nmap = r_texture_blanknormalmap;
1229 skinframe->gloss = NULL;
1230 skinframe->glow = NULL;
1231 skinframe->fog = NULL;
1233 basepixels_width = image_width;
1234 basepixels_height = image_height;
1235 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1237 if (textureflags & TEXF_ALPHA)
1239 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1240 if (basepixels[j] < 255)
1242 if (j < basepixels_width * basepixels_height * 4)
1244 // has transparent pixels
1245 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1246 for (j = 0;j < image_width * image_height * 4;j += 4)
1251 pixels[j+3] = basepixels[j+3];
1253 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1258 // _norm is the name used by tenebrae and has been adopted as standard
1261 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1263 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1267 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1269 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1270 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1271 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1273 Mem_Free(bumppixels);
1275 else if (r_shadow_bumpscale_basetexture.value > 0)
1277 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1278 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1279 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1283 // _luma is supported for tenebrae compatibility
1284 // (I think it's a very stupid name, but oh well)
1285 // _glow is the preferred name
1286 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;}
1287 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;}
1288 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;}
1289 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;}
1292 Mem_Free(basepixels);
1297 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)
1302 for (i = 0;i < width*height;i++)
1303 if (((unsigned char *)&palette[in[i]])[3] > 0)
1305 if (i == width*height)
1308 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1311 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)
1314 unsigned char *temp1, *temp2;
1315 skinframe_t *skinframe;
1317 if (cls.state == ca_dedicated)
1320 // if already loaded just return it, otherwise make a new skinframe
1321 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1322 if (skinframe && skinframe->base)
1325 skinframe->stain = NULL;
1326 skinframe->merged = NULL;
1327 skinframe->base = r_texture_notexture;
1328 skinframe->pants = NULL;
1329 skinframe->shirt = NULL;
1330 skinframe->nmap = r_texture_blanknormalmap;
1331 skinframe->gloss = NULL;
1332 skinframe->glow = NULL;
1333 skinframe->fog = NULL;
1335 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1339 if (bitsperpixel == 32)
1341 if (r_shadow_bumpscale_basetexture.value > 0)
1343 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1344 temp2 = temp1 + width * height * 4;
1345 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1346 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1349 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1350 if (textureflags & TEXF_ALPHA)
1352 for (i = 3;i < width * height * 4;i += 4)
1353 if (skindata[i] < 255)
1355 if (i < width * height * 4)
1357 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1358 memcpy(fogpixels, skindata, width * height * 4);
1359 for (i = 0;i < width * height * 4;i += 4)
1360 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1361 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1362 Mem_Free(fogpixels);
1366 else if (bitsperpixel == 8)
1368 if (r_shadow_bumpscale_basetexture.value > 0)
1370 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1371 temp2 = temp1 + width * height * 4;
1372 if (bitsperpixel == 32)
1373 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1376 // use either a custom palette or the quake palette
1377 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1378 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1380 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1383 // use either a custom palette, or the quake palette
1384 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
1385 if (!palette && loadglowtexture)
1386 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1387 if (!palette && loadpantsandshirt)
1389 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1390 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1392 if (skinframe->pants || skinframe->shirt)
1393 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1394 if (textureflags & TEXF_ALPHA)
1396 // if not using a custom alphapalette, use the quake one
1398 alphapalette = palette_alpha;
1399 for (i = 0;i < width * height;i++)
1400 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1402 if (i < width * height)
1403 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1410 skinframe_t *R_SkinFrame_LoadMissing(void)
1412 skinframe_t *skinframe;
1414 if (cls.state == ca_dedicated)
1417 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1418 skinframe->stain = NULL;
1419 skinframe->merged = NULL;
1420 skinframe->base = r_texture_notexture;
1421 skinframe->pants = NULL;
1422 skinframe->shirt = NULL;
1423 skinframe->nmap = r_texture_blanknormalmap;
1424 skinframe->gloss = NULL;
1425 skinframe->glow = NULL;
1426 skinframe->fog = NULL;
1431 void gl_main_start(void)
1436 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1437 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1439 alpha = 1 - exp(r / ((double)x*(double)x));
1440 if (x == FOGMASKTABLEWIDTH - 1)
1442 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1445 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1446 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1448 // set up r_skinframe loading system for textures
1449 memset(&r_skinframe, 0, sizeof(r_skinframe));
1450 r_skinframe.loadsequence = 1;
1451 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1453 r_main_texturepool = R_AllocTexturePool();
1454 R_BuildBlankTextures();
1456 if (gl_texturecubemap)
1459 R_BuildNormalizationCube();
1461 R_BuildFogTexture();
1462 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1463 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1464 memset(&r_svbsp, 0, sizeof (r_svbsp));
1467 void gl_main_shutdown(void)
1469 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1470 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1472 // clear out the r_skinframe state
1473 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1474 memset(&r_skinframe, 0, sizeof(r_skinframe));
1477 Mem_Free(r_svbsp.nodes);
1478 memset(&r_svbsp, 0, sizeof (r_svbsp));
1479 R_FreeTexturePool(&r_main_texturepool);
1480 r_texture_blanknormalmap = NULL;
1481 r_texture_white = NULL;
1482 r_texture_black = NULL;
1483 r_texture_whitecube = NULL;
1484 r_texture_normalizationcube = NULL;
1485 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1489 extern void CL_ParseEntityLump(char *entitystring);
1490 void gl_main_newmap(void)
1492 // FIXME: move this code to client
1494 char *entities, entname[MAX_QPATH];
1497 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1498 l = (int)strlen(entname) - 4;
1499 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1501 memcpy(entname + l, ".ent", 5);
1502 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1504 CL_ParseEntityLump(entities);
1509 if (cl.worldmodel->brush.entities)
1510 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1514 void GL_Main_Init(void)
1516 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1518 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1519 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1520 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1521 if (gamemode == GAME_NEHAHRA)
1523 Cvar_RegisterVariable (&gl_fogenable);
1524 Cvar_RegisterVariable (&gl_fogdensity);
1525 Cvar_RegisterVariable (&gl_fogred);
1526 Cvar_RegisterVariable (&gl_foggreen);
1527 Cvar_RegisterVariable (&gl_fogblue);
1528 Cvar_RegisterVariable (&gl_fogstart);
1529 Cvar_RegisterVariable (&gl_fogend);
1531 Cvar_RegisterVariable(&r_depthfirst);
1532 Cvar_RegisterVariable(&r_nearclip);
1533 Cvar_RegisterVariable(&r_showbboxes);
1534 Cvar_RegisterVariable(&r_showsurfaces);
1535 Cvar_RegisterVariable(&r_showtris);
1536 Cvar_RegisterVariable(&r_shownormals);
1537 Cvar_RegisterVariable(&r_showlighting);
1538 Cvar_RegisterVariable(&r_showshadowvolumes);
1539 Cvar_RegisterVariable(&r_showcollisionbrushes);
1540 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1541 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1542 Cvar_RegisterVariable(&r_showdisabledepthtest);
1543 Cvar_RegisterVariable(&r_drawportals);
1544 Cvar_RegisterVariable(&r_drawentities);
1545 Cvar_RegisterVariable(&r_cullentities_trace);
1546 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1547 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1548 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1549 Cvar_RegisterVariable(&r_drawviewmodel);
1550 Cvar_RegisterVariable(&r_speeds);
1551 Cvar_RegisterVariable(&r_fullbrights);
1552 Cvar_RegisterVariable(&r_wateralpha);
1553 Cvar_RegisterVariable(&r_dynamic);
1554 Cvar_RegisterVariable(&r_fullbright);
1555 Cvar_RegisterVariable(&r_shadows);
1556 Cvar_RegisterVariable(&r_shadows_throwdistance);
1557 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1558 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1559 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1560 Cvar_RegisterVariable(&r_textureunits);
1561 Cvar_RegisterVariable(&r_glsl);
1562 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1563 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1564 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1565 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1566 Cvar_RegisterVariable(&r_lerpsprites);
1567 Cvar_RegisterVariable(&r_lerpmodels);
1568 Cvar_RegisterVariable(&r_waterscroll);
1569 Cvar_RegisterVariable(&r_bloom);
1570 Cvar_RegisterVariable(&r_bloom_colorscale);
1571 Cvar_RegisterVariable(&r_bloom_brighten);
1572 Cvar_RegisterVariable(&r_bloom_blur);
1573 Cvar_RegisterVariable(&r_bloom_resolution);
1574 Cvar_RegisterVariable(&r_bloom_colorexponent);
1575 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1576 Cvar_RegisterVariable(&r_hdr);
1577 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1578 Cvar_RegisterVariable(&r_glsl_contrastboost);
1579 Cvar_RegisterVariable(&r_hdr_glowintensity);
1580 Cvar_RegisterVariable(&r_hdr_range);
1581 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1582 Cvar_RegisterVariable(&developer_texturelogging);
1583 Cvar_RegisterVariable(&gl_lightmaps);
1584 Cvar_RegisterVariable(&r_test);
1585 Cvar_RegisterVariable(&r_batchmode);
1586 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1587 Cvar_SetValue("r_fullbrights", 0);
1588 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1591 extern void R_Textures_Init(void);
1592 extern void GL_Draw_Init(void);
1593 extern void GL_Main_Init(void);
1594 extern void R_Shadow_Init(void);
1595 extern void R_Sky_Init(void);
1596 extern void GL_Surf_Init(void);
1597 extern void R_Light_Init(void);
1598 extern void R_Particles_Init(void);
1599 extern void R_Explosion_Init(void);
1600 extern void gl_backend_init(void);
1601 extern void Sbar_Init(void);
1602 extern void R_LightningBeams_Init(void);
1603 extern void Mod_RenderInit(void);
1605 void Render_Init(void)
1618 R_LightningBeams_Init();
1627 extern char *ENGINE_EXTENSIONS;
1630 VID_CheckExtensions();
1632 // LordHavoc: report supported extensions
1633 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1635 // clear to black (loading plaque will be seen over this)
1637 qglClearColor(0,0,0,1);CHECKGLERROR
1638 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1641 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1645 for (i = 0;i < 4;i++)
1647 p = r_view.frustum + i;
1652 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1656 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1660 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1664 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1668 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1672 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1676 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1680 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1688 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1692 for (i = 0;i < numplanes;i++)
1699 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1703 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1707 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1711 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1715 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1719 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1723 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1727 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1735 //==================================================================================
1737 static void R_UpdateEntityLighting(entity_render_t *ent)
1739 vec3_t tempdiffusenormal;
1741 // fetch the lighting from the worldmodel data
1742 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));
1743 VectorClear(ent->modellight_diffuse);
1744 VectorClear(tempdiffusenormal);
1745 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1748 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1749 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1752 VectorSet(ent->modellight_ambient, 1, 1, 1);
1754 // move the light direction into modelspace coordinates for lighting code
1755 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1756 if(VectorLength2(ent->modellight_lightdir) > 0)
1758 VectorNormalize(ent->modellight_lightdir);
1762 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1765 // scale ambient and directional light contributions according to rendering variables
1766 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1767 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1768 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1769 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1770 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1771 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1774 static void R_View_UpdateEntityVisible (void)
1777 entity_render_t *ent;
1779 if (!r_drawentities.integer)
1782 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1783 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1785 // worldmodel can check visibility
1786 for (i = 0;i < r_refdef.numentities;i++)
1788 ent = r_refdef.entities[i];
1789 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));
1791 if(r_cullentities_trace.integer)
1793 for (i = 0;i < r_refdef.numentities;i++)
1795 ent = r_refdef.entities[i];
1796 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1798 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1799 ent->last_trace_visibility = realtime;
1800 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1801 r_viewcache.entityvisible[i] = 0;
1808 // no worldmodel or it can't check visibility
1809 for (i = 0;i < r_refdef.numentities;i++)
1811 ent = r_refdef.entities[i];
1812 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1816 // update entity lighting (even on hidden entities for r_shadows)
1817 for (i = 0;i < r_refdef.numentities;i++)
1818 R_UpdateEntityLighting(r_refdef.entities[i]);
1821 // only used if skyrendermasked, and normally returns false
1822 int R_DrawBrushModelsSky (void)
1825 entity_render_t *ent;
1827 if (!r_drawentities.integer)
1831 for (i = 0;i < r_refdef.numentities;i++)
1833 if (!r_viewcache.entityvisible[i])
1835 ent = r_refdef.entities[i];
1836 if (!ent->model || !ent->model->DrawSky)
1838 ent->model->DrawSky(ent);
1844 void R_DrawNoModel(entity_render_t *ent);
1845 void R_DrawModels(void)
1848 entity_render_t *ent;
1850 if (!r_drawentities.integer)
1853 for (i = 0;i < r_refdef.numentities;i++)
1855 if (!r_viewcache.entityvisible[i])
1857 ent = r_refdef.entities[i];
1858 r_refdef.stats.entities++;
1859 if (ent->model && ent->model->Draw != NULL)
1860 ent->model->Draw(ent);
1866 void R_DrawModelsDepth(void)
1869 entity_render_t *ent;
1871 if (!r_drawentities.integer)
1874 for (i = 0;i < r_refdef.numentities;i++)
1876 if (!r_viewcache.entityvisible[i])
1878 ent = r_refdef.entities[i];
1879 r_refdef.stats.entities++;
1880 if (ent->model && ent->model->DrawDepth != NULL)
1881 ent->model->DrawDepth(ent);
1885 static void R_View_SetFrustum(void)
1887 double slopex, slopey;
1889 // break apart the view matrix into vectors for various purposes
1890 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1891 VectorNegate(r_view.left, r_view.right);
1894 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1895 r_view.frustum[0].normal[1] = 0 - 0;
1896 r_view.frustum[0].normal[2] = -1 - 0;
1897 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1898 r_view.frustum[1].normal[1] = 0 + 0;
1899 r_view.frustum[1].normal[2] = -1 + 0;
1900 r_view.frustum[2].normal[0] = 0 - 0;
1901 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1902 r_view.frustum[2].normal[2] = -1 - 0;
1903 r_view.frustum[3].normal[0] = 0 + 0;
1904 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1905 r_view.frustum[3].normal[2] = -1 + 0;
1909 zNear = r_refdef.nearclip;
1910 nudge = 1.0 - 1.0 / (1<<23);
1911 r_view.frustum[4].normal[0] = 0 - 0;
1912 r_view.frustum[4].normal[1] = 0 - 0;
1913 r_view.frustum[4].normal[2] = -1 - -nudge;
1914 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1915 r_view.frustum[5].normal[0] = 0 + 0;
1916 r_view.frustum[5].normal[1] = 0 + 0;
1917 r_view.frustum[5].normal[2] = -1 + -nudge;
1918 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1924 r_view.frustum[0].normal[0] = m[3] - m[0];
1925 r_view.frustum[0].normal[1] = m[7] - m[4];
1926 r_view.frustum[0].normal[2] = m[11] - m[8];
1927 r_view.frustum[0].dist = m[15] - m[12];
1929 r_view.frustum[1].normal[0] = m[3] + m[0];
1930 r_view.frustum[1].normal[1] = m[7] + m[4];
1931 r_view.frustum[1].normal[2] = m[11] + m[8];
1932 r_view.frustum[1].dist = m[15] + m[12];
1934 r_view.frustum[2].normal[0] = m[3] - m[1];
1935 r_view.frustum[2].normal[1] = m[7] - m[5];
1936 r_view.frustum[2].normal[2] = m[11] - m[9];
1937 r_view.frustum[2].dist = m[15] - m[13];
1939 r_view.frustum[3].normal[0] = m[3] + m[1];
1940 r_view.frustum[3].normal[1] = m[7] + m[5];
1941 r_view.frustum[3].normal[2] = m[11] + m[9];
1942 r_view.frustum[3].dist = m[15] + m[13];
1944 r_view.frustum[4].normal[0] = m[3] - m[2];
1945 r_view.frustum[4].normal[1] = m[7] - m[6];
1946 r_view.frustum[4].normal[2] = m[11] - m[10];
1947 r_view.frustum[4].dist = m[15] - m[14];
1949 r_view.frustum[5].normal[0] = m[3] + m[2];
1950 r_view.frustum[5].normal[1] = m[7] + m[6];
1951 r_view.frustum[5].normal[2] = m[11] + m[10];
1952 r_view.frustum[5].dist = m[15] + m[14];
1957 if (r_view.useperspective)
1959 slopex = 1.0 / r_view.frustum_x;
1960 slopey = 1.0 / r_view.frustum_y;
1961 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1962 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1963 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1964 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1965 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1967 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1968 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1969 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1970 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1971 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1973 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1974 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1975 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1976 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1977 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1981 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1982 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
1983 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1984 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
1985 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1986 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1987 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1988 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
1989 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
1990 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1993 PlaneClassify(&r_view.frustum[0]);
1994 PlaneClassify(&r_view.frustum[1]);
1995 PlaneClassify(&r_view.frustum[2]);
1996 PlaneClassify(&r_view.frustum[3]);
1997 PlaneClassify(&r_view.frustum[4]);
1999 // LordHavoc: note to all quake engine coders, Quake had a special case
2000 // for 90 degrees which assumed a square view (wrong), so I removed it,
2001 // Quake2 has it disabled as well.
2003 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2004 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2005 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2006 //PlaneClassify(&frustum[0]);
2008 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2009 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2010 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2011 //PlaneClassify(&frustum[1]);
2013 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2014 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2015 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2016 //PlaneClassify(&frustum[2]);
2018 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2019 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2020 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2021 //PlaneClassify(&frustum[3]);
2024 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2025 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2026 //PlaneClassify(&frustum[4]);
2029 void R_View_Update(void)
2031 R_View_SetFrustum();
2032 R_View_WorldVisibility();
2033 R_View_UpdateEntityVisible();
2036 void R_SetupView(const matrix4x4_t *matrix)
2038 if (!r_view.useperspective)
2039 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);
2040 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2041 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2043 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2045 GL_SetupView_Orientation_FromEntity(matrix);
2048 void R_ResetViewRendering2D(void)
2050 if (gl_support_fragment_shader)
2052 qglUseProgramObjectARB(0);CHECKGLERROR
2057 // GL is weird because it's bottom to top, r_view.y is top to bottom
2058 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2059 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2060 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2061 GL_Color(1, 1, 1, 1);
2062 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2063 GL_BlendFunc(GL_ONE, GL_ZERO);
2064 GL_AlphaTest(false);
2065 GL_ScissorTest(false);
2066 GL_DepthMask(false);
2067 GL_DepthRange(0, 1);
2068 GL_DepthTest(false);
2069 R_Mesh_Matrix(&identitymatrix);
2070 R_Mesh_ResetTextureState();
2071 GL_PolygonOffset(0, 0);
2072 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2073 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2074 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2075 qglStencilMask(~0);CHECKGLERROR
2076 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2077 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2078 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2081 void R_ResetViewRendering3D(void)
2083 if (gl_support_fragment_shader)
2085 qglUseProgramObjectARB(0);CHECKGLERROR
2090 // GL is weird because it's bottom to top, r_view.y is top to bottom
2091 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2092 R_SetupView(&r_view.matrix);
2093 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2094 GL_Color(1, 1, 1, 1);
2095 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2096 GL_BlendFunc(GL_ONE, GL_ZERO);
2097 GL_AlphaTest(false);
2098 GL_ScissorTest(true);
2100 GL_DepthRange(0, 1);
2102 R_Mesh_Matrix(&identitymatrix);
2103 R_Mesh_ResetTextureState();
2104 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2105 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2106 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2107 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2108 qglStencilMask(~0);CHECKGLERROR
2109 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2110 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2111 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2115 R_Bloom_SetupShader(
2117 "// written by Forest 'LordHavoc' Hale\n"
2119 "// common definitions between vertex shader and fragment shader:\n"
2121 "#ifdef __GLSL_CG_DATA_TYPES\n"
2122 "#define myhalf half\n"
2123 "#define myhvec2 hvec2\n"
2124 "#define myhvec3 hvec3\n"
2125 "#define myhvec4 hvec4\n"
2127 "#define myhalf float\n"
2128 "#define myhvec2 vec2\n"
2129 "#define myhvec3 vec3\n"
2130 "#define myhvec4 vec4\n"
2133 "varying vec2 ScreenTexCoord;\n"
2134 "varying vec2 BloomTexCoord;\n"
2139 "// vertex shader specific:\n"
2140 "#ifdef VERTEX_SHADER\n"
2144 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2145 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2146 " // transform vertex to camera space, using ftransform to match non-VS\n"
2148 " gl_Position = ftransform();\n"
2151 "#endif // VERTEX_SHADER\n"
2156 "// fragment shader specific:\n"
2157 "#ifdef FRAGMENT_SHADER\n"
2162 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2163 " for (x = -BLUR_X;x <= BLUR_X;x++)
2164 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2165 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2166 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2167 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2169 " gl_FragColor = vec4(color);\n"
2172 "#endif // FRAGMENT_SHADER\n"
2175 void R_RenderScene(void);
2177 void R_Bloom_StartFrame(void)
2179 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2181 // set bloomwidth and bloomheight to the bloom resolution that will be
2182 // used (often less than the screen resolution for faster rendering)
2183 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2184 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2185 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2187 // calculate desired texture sizes
2188 if (gl_support_arb_texture_non_power_of_two)
2190 screentexturewidth = r_view.width;
2191 screentextureheight = r_view.height;
2192 bloomtexturewidth = r_bloomstate.bloomwidth;
2193 bloomtextureheight = r_bloomstate.bloomheight;
2197 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2198 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2199 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2200 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2205 screentexturewidth = screentextureheight = 0;
2207 else if (r_bloom.integer)
2212 screentexturewidth = screentextureheight = 0;
2213 bloomtexturewidth = bloomtextureheight = 0;
2216 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)
2218 // can't use bloom if the parameters are too weird
2219 // can't use bloom if the card does not support the texture size
2220 if (r_bloomstate.texture_screen)
2221 R_FreeTexture(r_bloomstate.texture_screen);
2222 if (r_bloomstate.texture_bloom)
2223 R_FreeTexture(r_bloomstate.texture_bloom);
2224 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2228 r_bloomstate.enabled = true;
2229 r_bloomstate.hdr = r_hdr.integer != 0;
2231 // allocate textures as needed
2232 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2234 if (r_bloomstate.texture_screen)
2235 R_FreeTexture(r_bloomstate.texture_screen);
2236 r_bloomstate.texture_screen = NULL;
2237 r_bloomstate.screentexturewidth = screentexturewidth;
2238 r_bloomstate.screentextureheight = screentextureheight;
2239 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2240 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);
2242 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2244 if (r_bloomstate.texture_bloom)
2245 R_FreeTexture(r_bloomstate.texture_bloom);
2246 r_bloomstate.texture_bloom = NULL;
2247 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2248 r_bloomstate.bloomtextureheight = bloomtextureheight;
2249 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2250 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);
2253 // set up a texcoord array for the full resolution screen image
2254 // (we have to keep this around to copy back during final render)
2255 r_bloomstate.screentexcoord2f[0] = 0;
2256 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2257 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2258 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2259 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2260 r_bloomstate.screentexcoord2f[5] = 0;
2261 r_bloomstate.screentexcoord2f[6] = 0;
2262 r_bloomstate.screentexcoord2f[7] = 0;
2264 // set up a texcoord array for the reduced resolution bloom image
2265 // (which will be additive blended over the screen image)
2266 r_bloomstate.bloomtexcoord2f[0] = 0;
2267 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2268 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2269 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2270 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2271 r_bloomstate.bloomtexcoord2f[5] = 0;
2272 r_bloomstate.bloomtexcoord2f[6] = 0;
2273 r_bloomstate.bloomtexcoord2f[7] = 0;
2276 void R_Bloom_CopyScreenTexture(float colorscale)
2278 r_refdef.stats.bloom++;
2280 R_ResetViewRendering2D();
2281 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2282 R_Mesh_ColorPointer(NULL, 0, 0);
2283 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2284 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2286 // copy view into the screen texture
2287 GL_ActiveTexture(0);
2289 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
2290 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2292 // now scale it down to the bloom texture size
2294 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2295 GL_BlendFunc(GL_ONE, GL_ZERO);
2296 GL_Color(colorscale, colorscale, colorscale, 1);
2297 // TODO: optimize with multitexture or GLSL
2298 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2299 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2301 // we now have a bloom image in the framebuffer
2302 // copy it into the bloom image texture for later processing
2303 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2304 GL_ActiveTexture(0);
2306 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
2307 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2310 void R_Bloom_CopyHDRTexture(void)
2312 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2313 GL_ActiveTexture(0);
2315 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
2316 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2319 void R_Bloom_MakeTexture(void)
2322 float xoffset, yoffset, r, brighten;
2324 r_refdef.stats.bloom++;
2326 R_ResetViewRendering2D();
2327 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2328 R_Mesh_ColorPointer(NULL, 0, 0);
2330 // we have a bloom image in the framebuffer
2332 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2334 for (x = 1;x < r_bloom_colorexponent.value;)
2337 r = bound(0, r_bloom_colorexponent.value / x, 1);
2338 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2339 GL_Color(r, r, r, 1);
2340 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2341 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2342 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2343 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2345 // copy the vertically blurred bloom view to a texture
2346 GL_ActiveTexture(0);
2348 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
2349 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2352 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2353 brighten = r_bloom_brighten.value;
2355 brighten *= r_hdr_range.value;
2356 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2357 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2359 for (dir = 0;dir < 2;dir++)
2361 // blend on at multiple vertical offsets to achieve a vertical blur
2362 // TODO: do offset blends using GLSL
2363 GL_BlendFunc(GL_ONE, GL_ZERO);
2364 for (x = -range;x <= range;x++)
2366 if (!dir){xoffset = 0;yoffset = x;}
2367 else {xoffset = x;yoffset = 0;}
2368 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2369 yoffset /= (float)r_bloomstate.bloomtextureheight;
2370 // compute a texcoord array with the specified x and y offset
2371 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2372 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2373 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2374 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2375 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2376 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2377 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2378 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2379 // this r value looks like a 'dot' particle, fading sharply to
2380 // black at the edges
2381 // (probably not realistic but looks good enough)
2382 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2383 //r = (dir ? 1.0f : brighten)/(range*2+1);
2384 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2385 GL_Color(r, r, r, 1);
2386 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2387 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2388 GL_BlendFunc(GL_ONE, GL_ONE);
2391 // copy the vertically blurred bloom view to a texture
2392 GL_ActiveTexture(0);
2394 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
2395 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2398 // apply subtract last
2399 // (just like it would be in a GLSL shader)
2400 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2402 GL_BlendFunc(GL_ONE, GL_ZERO);
2403 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2404 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2405 GL_Color(1, 1, 1, 1);
2406 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2407 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2409 GL_BlendFunc(GL_ONE, GL_ONE);
2410 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2411 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2412 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2413 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2414 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2415 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2416 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2418 // copy the darkened bloom view to a texture
2419 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2420 GL_ActiveTexture(0);
2422 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
2423 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2427 void R_HDR_RenderBloomTexture(void)
2429 int oldwidth, oldheight;
2431 oldwidth = r_view.width;
2432 oldheight = r_view.height;
2433 r_view.width = r_bloomstate.bloomwidth;
2434 r_view.height = r_bloomstate.bloomheight;
2436 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2437 // TODO: add exposure compensation features
2438 // TODO: add fp16 framebuffer support
2440 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2442 r_view.colorscale /= r_hdr_range.value;
2445 R_ResetViewRendering2D();
2447 R_Bloom_CopyHDRTexture();
2448 R_Bloom_MakeTexture();
2450 R_ResetViewRendering3D();
2453 if (r_timereport_active)
2454 R_TimeReport("clear");
2457 // restore the view settings
2458 r_view.width = oldwidth;
2459 r_view.height = oldheight;
2462 static void R_BlendView(void)
2464 if (r_bloomstate.enabled && r_bloomstate.hdr)
2466 // render high dynamic range bloom effect
2467 // the bloom texture was made earlier this render, so we just need to
2468 // blend it onto the screen...
2469 R_ResetViewRendering2D();
2470 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2471 R_Mesh_ColorPointer(NULL, 0, 0);
2472 GL_Color(1, 1, 1, 1);
2473 GL_BlendFunc(GL_ONE, GL_ONE);
2474 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2475 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2476 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2477 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2479 else if (r_bloomstate.enabled)
2481 // render simple bloom effect
2482 // copy the screen and shrink it and darken it for the bloom process
2483 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2484 // make the bloom texture
2485 R_Bloom_MakeTexture();
2486 // put the original screen image back in place and blend the bloom
2488 R_ResetViewRendering2D();
2489 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2490 R_Mesh_ColorPointer(NULL, 0, 0);
2491 GL_Color(1, 1, 1, 1);
2492 GL_BlendFunc(GL_ONE, GL_ZERO);
2493 // do both in one pass if possible
2494 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2495 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2496 if (r_textureunits.integer >= 2 && gl_combine.integer)
2498 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2499 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2500 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2504 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2505 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2506 // now blend on the bloom texture
2507 GL_BlendFunc(GL_ONE, GL_ONE);
2508 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2509 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2511 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2512 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2514 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2516 // apply a color tint to the whole view
2517 R_ResetViewRendering2D();
2518 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2519 R_Mesh_ColorPointer(NULL, 0, 0);
2520 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2521 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2522 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2526 void R_RenderScene(void);
2528 matrix4x4_t r_waterscrollmatrix;
2530 void R_UpdateVariables(void)
2534 r_refdef.farclip = 4096;
2535 if (r_refdef.worldmodel)
2536 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2537 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2539 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2540 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2541 r_refdef.polygonfactor = 0;
2542 r_refdef.polygonoffset = 0;
2543 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2544 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2546 r_refdef.rtworld = r_shadow_realtime_world.integer;
2547 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2548 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2549 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2550 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2551 if (r_showsurfaces.integer)
2553 r_refdef.rtworld = false;
2554 r_refdef.rtworldshadows = false;
2555 r_refdef.rtdlight = false;
2556 r_refdef.rtdlightshadows = false;
2557 r_refdef.lightmapintensity = 0;
2560 if (gamemode == GAME_NEHAHRA)
2562 if (gl_fogenable.integer)
2564 r_refdef.oldgl_fogenable = true;
2565 r_refdef.fog_density = gl_fogdensity.value;
2566 r_refdef.fog_red = gl_fogred.value;
2567 r_refdef.fog_green = gl_foggreen.value;
2568 r_refdef.fog_blue = gl_fogblue.value;
2570 else if (r_refdef.oldgl_fogenable)
2572 r_refdef.oldgl_fogenable = false;
2573 r_refdef.fog_density = 0;
2574 r_refdef.fog_red = 0;
2575 r_refdef.fog_green = 0;
2576 r_refdef.fog_blue = 0;
2579 if (r_refdef.fog_density)
2581 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2582 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2583 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2585 if (r_refdef.fog_density)
2587 r_refdef.fogenabled = true;
2588 // this is the point where the fog reaches 0.9986 alpha, which we
2589 // consider a good enough cutoff point for the texture
2590 // (0.9986 * 256 == 255.6)
2591 r_refdef.fogrange = 400 / r_refdef.fog_density;
2592 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2593 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2594 // fog color was already set
2597 r_refdef.fogenabled = false;
2605 void R_RenderView(void)
2607 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2608 return; //Host_Error ("R_RenderView: NULL worldmodel");
2610 R_Shadow_UpdateWorldLightSelection();
2613 if (r_timereport_active)
2614 R_TimeReport("setup");
2617 if (r_timereport_active)
2618 R_TimeReport("visibility");
2620 R_ResetViewRendering3D();
2623 if (r_timereport_active)
2624 R_TimeReport("clear");
2626 R_Bloom_StartFrame();
2628 // this produces a bloom texture to be used in R_BlendView() later
2630 R_HDR_RenderBloomTexture();
2632 r_view.colorscale = r_hdr_scenebrightness.value;
2636 if (r_timereport_active)
2637 R_TimeReport("blendview");
2639 GL_Scissor(0, 0, vid.width, vid.height);
2640 GL_ScissorTest(false);
2644 extern void R_DrawLightningBeams (void);
2645 extern void VM_CL_AddPolygonsToMeshQueue (void);
2646 extern void R_DrawPortals (void);
2647 extern cvar_t cl_locs_show;
2648 static void R_DrawLocs(void);
2649 static void R_DrawEntityBBoxes(void);
2650 void R_RenderScene(void)
2652 // don't let sound skip if going slow
2653 if (r_refdef.extraupdate)
2656 R_ResetViewRendering3D();
2658 R_MeshQueue_BeginScene();
2662 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);
2664 if (cl.csqc_vidvars.drawworld)
2666 // don't let sound skip if going slow
2667 if (r_refdef.extraupdate)
2670 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2672 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2673 if (r_timereport_active)
2674 R_TimeReport("worldsky");
2677 if (R_DrawBrushModelsSky() && r_timereport_active)
2678 R_TimeReport("bmodelsky");
2681 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2683 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2684 if (r_timereport_active)
2685 R_TimeReport("worlddepth");
2687 if (r_depthfirst.integer >= 2)
2689 R_DrawModelsDepth();
2690 if (r_timereport_active)
2691 R_TimeReport("modeldepth");
2694 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2696 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2697 if (r_timereport_active)
2698 R_TimeReport("world");
2701 // don't let sound skip if going slow
2702 if (r_refdef.extraupdate)
2706 if (r_timereport_active)
2707 R_TimeReport("models");
2709 // don't let sound skip if going slow
2710 if (r_refdef.extraupdate)
2713 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2715 R_DrawModelShadows();
2717 R_ResetViewRendering3D();
2719 // don't let sound skip if going slow
2720 if (r_refdef.extraupdate)
2724 R_ShadowVolumeLighting(false);
2725 if (r_timereport_active)
2726 R_TimeReport("rtlights");
2728 // don't let sound skip if going slow
2729 if (r_refdef.extraupdate)
2732 if (cl.csqc_vidvars.drawworld)
2734 R_DrawLightningBeams();
2735 if (r_timereport_active)
2736 R_TimeReport("lightning");
2739 if (r_timereport_active)
2740 R_TimeReport("particles");
2743 if (r_timereport_active)
2744 R_TimeReport("explosions");
2747 if (gl_support_fragment_shader)
2749 qglUseProgramObjectARB(0);CHECKGLERROR
2751 VM_CL_AddPolygonsToMeshQueue();
2753 if (cl_locs_show.integer)
2756 if (r_timereport_active)
2757 R_TimeReport("showlocs");
2760 if (r_drawportals.integer)
2763 if (r_timereport_active)
2764 R_TimeReport("portals");
2767 if (r_showbboxes.value > 0)
2769 R_DrawEntityBBoxes();
2770 if (r_timereport_active)
2771 R_TimeReport("bboxes");
2774 if (gl_support_fragment_shader)
2776 qglUseProgramObjectARB(0);CHECKGLERROR
2778 R_MeshQueue_RenderTransparent();
2779 if (r_timereport_active)
2780 R_TimeReport("drawtrans");
2782 if (gl_support_fragment_shader)
2784 qglUseProgramObjectARB(0);CHECKGLERROR
2787 if (cl.csqc_vidvars.drawworld)
2790 if (r_timereport_active)
2791 R_TimeReport("coronas");
2794 // don't let sound skip if going slow
2795 if (r_refdef.extraupdate)
2798 R_ResetViewRendering2D();
2801 static const int bboxelements[36] =
2811 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2814 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2815 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2816 GL_DepthMask(false);
2817 GL_DepthRange(0, 1);
2818 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2819 R_Mesh_Matrix(&identitymatrix);
2820 R_Mesh_ResetTextureState();
2822 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2823 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2824 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2825 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2826 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2827 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2828 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2829 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2830 R_FillColors(color4f, 8, cr, cg, cb, ca);
2831 if (r_refdef.fogenabled)
2833 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2835 f1 = FogPoint_World(v);
2837 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2838 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2839 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2842 R_Mesh_VertexPointer(vertex3f, 0, 0);
2843 R_Mesh_ColorPointer(color4f, 0, 0);
2844 R_Mesh_ResetTextureState();
2845 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2848 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2852 prvm_edict_t *edict;
2853 // this function draws bounding boxes of server entities
2857 for (i = 0;i < numsurfaces;i++)
2859 edict = PRVM_EDICT_NUM(surfacelist[i]);
2860 switch ((int)edict->fields.server->solid)
2862 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2863 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2864 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2865 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2866 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2867 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2869 color[3] *= r_showbboxes.value;
2870 color[3] = bound(0, color[3], 1);
2871 GL_DepthTest(!r_showdisabledepthtest.integer);
2872 GL_CullFace(GL_BACK);
2873 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2878 static void R_DrawEntityBBoxes(void)
2881 prvm_edict_t *edict;
2883 // this function draws bounding boxes of server entities
2887 for (i = 0;i < prog->num_edicts;i++)
2889 edict = PRVM_EDICT_NUM(i);
2890 if (edict->priv.server->free)
2892 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2893 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2898 int nomodelelements[24] =
2910 float nomodelvertex3f[6*3] =
2920 float nomodelcolor4f[6*4] =
2922 0.0f, 0.0f, 0.5f, 1.0f,
2923 0.0f, 0.0f, 0.5f, 1.0f,
2924 0.0f, 0.5f, 0.0f, 1.0f,
2925 0.0f, 0.5f, 0.0f, 1.0f,
2926 0.5f, 0.0f, 0.0f, 1.0f,
2927 0.5f, 0.0f, 0.0f, 1.0f
2930 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2935 // this is only called once per entity so numsurfaces is always 1, and
2936 // surfacelist is always {0}, so this code does not handle batches
2937 R_Mesh_Matrix(&ent->matrix);
2939 if (ent->flags & EF_ADDITIVE)
2941 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2942 GL_DepthMask(false);
2944 else if (ent->alpha < 1)
2946 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2947 GL_DepthMask(false);
2951 GL_BlendFunc(GL_ONE, GL_ZERO);
2954 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2955 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2956 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2957 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2958 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2959 if (r_refdef.fogenabled)
2962 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2963 R_Mesh_ColorPointer(color4f, 0, 0);
2964 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2965 f1 = FogPoint_World(org);
2967 for (i = 0, c = color4f;i < 6;i++, c += 4)
2969 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2970 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2971 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2975 else if (ent->alpha != 1)
2977 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2978 R_Mesh_ColorPointer(color4f, 0, 0);
2979 for (i = 0, c = color4f;i < 6;i++, c += 4)
2983 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2984 R_Mesh_ResetTextureState();
2985 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2988 void R_DrawNoModel(entity_render_t *ent)
2991 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2992 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2993 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
2995 // R_DrawNoModelCallback(ent, 0);
2998 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3000 vec3_t right1, right2, diff, normal;
3002 VectorSubtract (org2, org1, normal);
3004 // calculate 'right' vector for start
3005 VectorSubtract (r_view.origin, org1, diff);
3006 CrossProduct (normal, diff, right1);
3007 VectorNormalize (right1);
3009 // calculate 'right' vector for end
3010 VectorSubtract (r_view.origin, org2, diff);
3011 CrossProduct (normal, diff, right2);
3012 VectorNormalize (right2);
3014 vert[ 0] = org1[0] + width * right1[0];
3015 vert[ 1] = org1[1] + width * right1[1];
3016 vert[ 2] = org1[2] + width * right1[2];
3017 vert[ 3] = org1[0] - width * right1[0];
3018 vert[ 4] = org1[1] - width * right1[1];
3019 vert[ 5] = org1[2] - width * right1[2];
3020 vert[ 6] = org2[0] - width * right2[0];
3021 vert[ 7] = org2[1] - width * right2[1];
3022 vert[ 8] = org2[2] - width * right2[2];
3023 vert[ 9] = org2[0] + width * right2[0];
3024 vert[10] = org2[1] + width * right2[1];
3025 vert[11] = org2[2] + width * right2[2];
3028 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3030 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)
3035 if (r_refdef.fogenabled)
3036 fog = FogPoint_World(origin);
3038 R_Mesh_Matrix(&identitymatrix);
3039 GL_BlendFunc(blendfunc1, blendfunc2);
3045 GL_CullFace(GL_BACK);
3048 GL_CullFace(GL_FRONT);
3050 GL_DepthMask(false);
3051 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3052 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3053 GL_DepthTest(!depthdisable);
3055 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3056 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3057 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3058 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3059 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3060 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3061 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3062 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3063 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3064 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3065 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3066 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3068 R_Mesh_VertexPointer(vertex3f, 0, 0);
3069 R_Mesh_ColorPointer(NULL, 0, 0);
3070 R_Mesh_ResetTextureState();
3071 R_Mesh_TexBind(0, R_GetTexture(texture));
3072 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3073 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3074 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3075 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3077 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3079 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3080 GL_BlendFunc(blendfunc1, GL_ONE);
3082 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);
3083 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3087 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3092 VectorSet(v, x, y, z);
3093 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3094 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3096 if (i == mesh->numvertices)
3098 if (mesh->numvertices < mesh->maxvertices)
3100 VectorCopy(v, vertex3f);
3101 mesh->numvertices++;
3103 return mesh->numvertices;
3109 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3113 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3114 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3115 e = mesh->element3i + mesh->numtriangles * 3;
3116 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3118 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3119 if (mesh->numtriangles < mesh->maxtriangles)
3124 mesh->numtriangles++;
3126 element[1] = element[2];
3130 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3134 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3135 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3136 e = mesh->element3i + mesh->numtriangles * 3;
3137 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3139 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3140 if (mesh->numtriangles < mesh->maxtriangles)
3145 mesh->numtriangles++;
3147 element[1] = element[2];
3151 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3152 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3154 int planenum, planenum2;
3157 mplane_t *plane, *plane2;
3159 double temppoints[2][256*3];
3160 // figure out how large a bounding box we need to properly compute this brush
3162 for (w = 0;w < numplanes;w++)
3163 maxdist = max(maxdist, planes[w].dist);
3164 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3165 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3166 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3170 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3171 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3173 if (planenum2 == planenum)
3175 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);
3178 if (tempnumpoints < 3)
3180 // generate elements forming a triangle fan for this polygon
3181 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3185 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3188 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3189 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3190 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);
3191 GL_LockArrays(0, brush->numpoints);
3192 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3193 GL_LockArrays(0, 0);
3196 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3199 if (!surface->num_collisiontriangles)
3201 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3202 i = (int)(((size_t)surface) / sizeof(msurface_t));
3203 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);
3204 GL_LockArrays(0, surface->num_collisionvertices);
3205 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3206 GL_LockArrays(0, 0);
3209 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)
3211 texturelayer_t *layer;
3212 layer = t->currentlayers + t->currentnumlayers++;
3214 layer->depthmask = depthmask;
3215 layer->blendfunc1 = blendfunc1;
3216 layer->blendfunc2 = blendfunc2;
3217 layer->texture = texture;
3218 layer->texmatrix = *matrix;
3219 layer->color[0] = r * r_view.colorscale;
3220 layer->color[1] = g * r_view.colorscale;
3221 layer->color[2] = b * r_view.colorscale;
3222 layer->color[3] = a;
3225 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3228 index = parms[2] + r_refdef.time * parms[3];
3229 index -= floor(index);
3233 case Q3WAVEFUNC_NONE:
3234 case Q3WAVEFUNC_NOISE:
3235 case Q3WAVEFUNC_COUNT:
3238 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3239 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3240 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3241 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3242 case Q3WAVEFUNC_TRIANGLE:
3244 f = index - floor(index);
3255 return (float)(parms[0] + parms[1] * f);
3258 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3261 model_t *model = ent->model;
3264 q3shaderinfo_layer_tcmod_t *tcmod;
3266 // switch to an alternate material if this is a q1bsp animated material
3268 texture_t *texture = t;
3269 int s = ent->skinnum;
3270 if ((unsigned int)s >= (unsigned int)model->numskins)
3272 if (model->skinscenes)
3274 if (model->skinscenes[s].framecount > 1)
3275 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3277 s = model->skinscenes[s].firstframe;
3280 t = t + s * model->num_surfaces;
3283 // use an alternate animation if the entity's frame is not 0,
3284 // and only if the texture has an alternate animation
3285 if (ent->frame2 != 0 && t->anim_total[1])
3286 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3288 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3290 texture->currentframe = t;
3293 // update currentskinframe to be a qw skin or animation frame
3294 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3296 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3298 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3299 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3300 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);
3302 t->currentskinframe = r_qwskincache_skinframe[i];
3303 if (t->currentskinframe == NULL)
3304 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3306 else if (t->numskinframes >= 2)
3307 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3308 if (t->backgroundnumskinframes >= 2)
3309 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3311 t->currentmaterialflags = t->basematerialflags;
3312 t->currentalpha = ent->alpha;
3313 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3314 t->currentalpha *= r_wateralpha.value;
3315 if (!(ent->flags & RENDER_LIGHT))
3316 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3317 if (ent->effects & EF_ADDITIVE)
3318 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3319 else if (t->currentalpha < 1)
3320 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3321 if (ent->effects & EF_DOUBLESIDED)
3322 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3323 if (ent->effects & EF_NODEPTHTEST)
3324 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3325 if (ent->flags & RENDER_VIEWMODEL)
3326 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3327 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3328 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3330 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3333 switch(tcmod->tcmod)
3337 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3338 matrix = r_waterscrollmatrix;
3340 matrix = identitymatrix;
3342 case Q3TCMOD_ENTITYTRANSLATE:
3343 // this is used in Q3 to allow the gamecode to control texcoord
3344 // scrolling on the entity, which is not supported in darkplaces yet.
3345 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3347 case Q3TCMOD_ROTATE:
3348 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3349 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3350 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3353 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3355 case Q3TCMOD_SCROLL:
3356 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3358 case Q3TCMOD_STRETCH:
3359 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3360 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3362 case Q3TCMOD_TRANSFORM:
3363 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3364 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3365 VectorSet(tcmat + 6, 0 , 0 , 1);
3366 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3367 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3369 case Q3TCMOD_TURBULENT:
3370 // this is handled in the RSurf_PrepareVertices function
3371 matrix = identitymatrix;
3374 // either replace or concatenate the transformation
3376 t->currenttexmatrix = matrix;
3379 matrix4x4_t temp = t->currenttexmatrix;
3380 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3384 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3385 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3386 t->glosstexture = r_texture_white;
3387 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3388 t->backgroundglosstexture = r_texture_white;
3389 t->specularpower = r_shadow_glossexponent.value;
3390 // TODO: store reference values for these in the texture?
3391 t->specularscale = 0;
3392 if (r_shadow_gloss.integer > 0)
3394 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3396 if (r_shadow_glossintensity.value > 0)
3398 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3399 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3400 t->specularscale = r_shadow_glossintensity.value;
3403 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3404 t->specularscale = r_shadow_gloss2intensity.value;
3407 // lightmaps mode looks bad with dlights using actual texturing, so turn
3408 // off the colormap and glossmap, but leave the normalmap on as it still
3409 // accurately represents the shading involved
3410 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3412 t->basetexture = r_texture_white;
3413 t->specularscale = 0;
3416 t->currentpolygonfactor = r_refdef.polygonfactor;
3417 t->currentpolygonoffset = r_refdef.polygonoffset;
3418 // submodels are biased to avoid z-fighting with world surfaces that they
3419 // may be exactly overlapping (avoids z-fighting artifacts on certain
3420 // doors and things in Quake maps)
3421 if (ent->model->brush.submodel)
3423 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3424 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3427 VectorClear(t->dlightcolor);
3428 t->currentnumlayers = 0;
3429 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3431 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3433 int blendfunc1, blendfunc2, depthmask;
3434 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3436 blendfunc1 = GL_SRC_ALPHA;
3437 blendfunc2 = GL_ONE;
3439 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3441 blendfunc1 = GL_SRC_ALPHA;
3442 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3444 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3446 blendfunc1 = t->customblendfunc[0];
3447 blendfunc2 = t->customblendfunc[1];
3451 blendfunc1 = GL_ONE;
3452 blendfunc2 = GL_ZERO;
3454 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3455 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3457 rtexture_t *currentbasetexture;
3459 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3460 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3461 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3462 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3464 // fullbright is not affected by r_refdef.lightmapintensity
3465 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3466 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3467 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);
3468 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3469 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);
3474 // set the color tint used for lights affecting this surface
3475 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3477 // q3bsp has no lightmap updates, so the lightstylevalue that
3478 // would normally be baked into the lightmap must be
3479 // applied to the color
3480 if (ent->model->type == mod_brushq3)
3481 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3482 colorscale *= r_refdef.lightmapintensity;
3483 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);
3484 if (r_ambient.value >= (1.0f/64.0f))
3485 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);
3486 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3488 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);
3489 if (r_ambient.value >= (1.0f/64.0f))
3490 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);
3492 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3494 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);
3495 if (r_ambient.value >= (1.0f/64.0f))
3496 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);
3499 if (t->currentskinframe->glow != NULL)
3500 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);
3501 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3503 // if this is opaque use alpha blend which will darken the earlier
3506 // if this is an alpha blended material, all the earlier passes
3507 // were darkened by fog already, so we only need to add the fog
3508 // color ontop through the fog mask texture
3510 // if this is an additive blended material, all the earlier passes
3511 // were darkened by fog already, and we should not add fog color
3512 // (because the background was not darkened, there is no fog color
3513 // that was lost behind it).
3514 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);
3521 void R_UpdateAllTextureInfo(entity_render_t *ent)
3525 for (i = 0;i < ent->model->num_texturesperskin;i++)
3526 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3529 rsurfacestate_t rsurface;
3531 void R_Mesh_ResizeArrays(int newvertices)
3534 if (rsurface.array_size >= newvertices)
3536 if (rsurface.array_modelvertex3f)
3537 Mem_Free(rsurface.array_modelvertex3f);
3538 rsurface.array_size = (newvertices + 1023) & ~1023;
3539 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3540 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3541 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3542 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3543 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3544 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3545 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3546 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3547 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3548 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3549 rsurface.array_color4f = base + rsurface.array_size * 27;
3550 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3553 void RSurf_CleanUp(void)
3556 if (rsurface.mode == RSURFMODE_GLSL)
3558 qglUseProgramObjectARB(0);CHECKGLERROR
3560 GL_AlphaTest(false);
3561 rsurface.mode = RSURFMODE_NONE;
3562 rsurface.uselightmaptexture = false;
3563 rsurface.texture = NULL;
3566 void RSurf_ActiveWorldEntity(void)
3568 model_t *model = r_refdef.worldmodel;
3570 if (rsurface.array_size < model->surfmesh.num_vertices)
3571 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3572 rsurface.matrix = identitymatrix;
3573 rsurface.inversematrix = identitymatrix;
3574 R_Mesh_Matrix(&identitymatrix);
3575 VectorCopy(r_view.origin, rsurface.modelorg);
3576 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3577 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3578 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3579 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3580 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3581 rsurface.frameblend[0].frame = 0;
3582 rsurface.frameblend[0].lerp = 1;
3583 rsurface.frameblend[1].frame = 0;
3584 rsurface.frameblend[1].lerp = 0;
3585 rsurface.frameblend[2].frame = 0;
3586 rsurface.frameblend[2].lerp = 0;
3587 rsurface.frameblend[3].frame = 0;
3588 rsurface.frameblend[3].lerp = 0;
3589 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3590 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3591 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3592 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3593 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3594 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3595 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3596 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3597 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3598 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3599 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3600 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3601 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3602 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3603 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3604 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3605 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3606 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3607 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3608 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3609 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3610 rsurface.modelelement3i = model->surfmesh.data_element3i;
3611 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3612 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3613 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3614 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3615 rsurface.modelsurfaces = model->data_surfaces;
3616 rsurface.generatedvertex = false;
3617 rsurface.vertex3f = rsurface.modelvertex3f;
3618 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3619 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3620 rsurface.svector3f = rsurface.modelsvector3f;
3621 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3622 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3623 rsurface.tvector3f = rsurface.modeltvector3f;
3624 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3625 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3626 rsurface.normal3f = rsurface.modelnormal3f;
3627 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3628 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3629 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3632 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3634 model_t *model = ent->model;
3636 if (rsurface.array_size < model->surfmesh.num_vertices)
3637 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3638 rsurface.matrix = ent->matrix;
3639 rsurface.inversematrix = ent->inversematrix;
3640 R_Mesh_Matrix(&rsurface.matrix);
3641 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3642 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3643 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3644 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3645 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3646 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3647 rsurface.frameblend[0] = ent->frameblend[0];
3648 rsurface.frameblend[1] = ent->frameblend[1];
3649 rsurface.frameblend[2] = ent->frameblend[2];
3650 rsurface.frameblend[3] = ent->frameblend[3];
3651 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3655 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3656 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3657 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3658 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3659 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3661 else if (wantnormals)
3663 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3664 rsurface.modelsvector3f = NULL;
3665 rsurface.modeltvector3f = NULL;
3666 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3667 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3671 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3672 rsurface.modelsvector3f = NULL;
3673 rsurface.modeltvector3f = NULL;
3674 rsurface.modelnormal3f = NULL;
3675 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3677 rsurface.modelvertex3f_bufferobject = 0;
3678 rsurface.modelvertex3f_bufferoffset = 0;
3679 rsurface.modelsvector3f_bufferobject = 0;
3680 rsurface.modelsvector3f_bufferoffset = 0;
3681 rsurface.modeltvector3f_bufferobject = 0;
3682 rsurface.modeltvector3f_bufferoffset = 0;
3683 rsurface.modelnormal3f_bufferobject = 0;
3684 rsurface.modelnormal3f_bufferoffset = 0;
3685 rsurface.generatedvertex = true;
3689 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3690 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3691 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3692 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3693 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3694 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3695 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3696 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3697 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3698 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3699 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3700 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3701 rsurface.generatedvertex = false;
3703 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3704 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3705 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3706 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3707 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3708 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3709 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3710 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3711 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3712 rsurface.modelelement3i = model->surfmesh.data_element3i;
3713 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3714 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3715 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3716 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3717 rsurface.modelsurfaces = model->data_surfaces;
3718 rsurface.vertex3f = rsurface.modelvertex3f;
3719 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3720 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3721 rsurface.svector3f = rsurface.modelsvector3f;
3722 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3723 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3724 rsurface.tvector3f = rsurface.modeltvector3f;
3725 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3726 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3727 rsurface.normal3f = rsurface.modelnormal3f;
3728 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3729 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3730 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3733 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3734 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3737 int texturesurfaceindex;
3742 const float *v1, *in_tc;
3744 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3746 q3shaderinfo_deform_t *deform;
3747 // 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
3748 if (rsurface.generatedvertex)
3750 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3751 generatenormals = true;
3752 for (i = 0;i < Q3MAXDEFORMS;i++)
3754 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3756 generatetangents = true;
3757 generatenormals = true;
3759 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3760 generatenormals = true;
3762 if (generatenormals && !rsurface.modelnormal3f)
3764 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3765 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3766 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3767 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3769 if (generatetangents && !rsurface.modelsvector3f)
3771 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3772 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3773 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3774 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3775 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3776 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3777 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);
3780 rsurface.vertex3f = rsurface.modelvertex3f;
3781 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3782 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3783 rsurface.svector3f = rsurface.modelsvector3f;
3784 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3785 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3786 rsurface.tvector3f = rsurface.modeltvector3f;
3787 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3788 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3789 rsurface.normal3f = rsurface.modelnormal3f;
3790 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3791 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3792 // if vertices are deformed (sprite flares and things in maps, possibly
3793 // water waves, bulges and other deformations), generate them into
3794 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3795 // (may be static model data or generated data for an animated model, or
3796 // the previous deform pass)
3797 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3799 switch (deform->deform)
3802 case Q3DEFORM_PROJECTIONSHADOW:
3803 case Q3DEFORM_TEXT0:
3804 case Q3DEFORM_TEXT1:
3805 case Q3DEFORM_TEXT2:
3806 case Q3DEFORM_TEXT3:
3807 case Q3DEFORM_TEXT4:
3808 case Q3DEFORM_TEXT5:
3809 case Q3DEFORM_TEXT6:
3810 case Q3DEFORM_TEXT7:
3813 case Q3DEFORM_AUTOSPRITE:
3814 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3815 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3816 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3817 VectorNormalize(newforward);
3818 VectorNormalize(newright);
3819 VectorNormalize(newup);
3820 // make deformed versions of only the model vertices used by the specified surfaces
3821 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3823 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3824 // a single autosprite surface can contain multiple sprites...
3825 for (j = 0;j < surface->num_vertices - 3;j += 4)
3827 VectorClear(center);
3828 for (i = 0;i < 4;i++)
3829 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3830 VectorScale(center, 0.25f, center);
3831 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3832 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3833 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3834 for (i = 0;i < 4;i++)
3836 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3837 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3840 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);
3841 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);
3843 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3844 rsurface.vertex3f_bufferobject = 0;
3845 rsurface.vertex3f_bufferoffset = 0;
3846 rsurface.svector3f = rsurface.array_deformedsvector3f;
3847 rsurface.svector3f_bufferobject = 0;
3848 rsurface.svector3f_bufferoffset = 0;
3849 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3850 rsurface.tvector3f_bufferobject = 0;
3851 rsurface.tvector3f_bufferoffset = 0;
3852 rsurface.normal3f = rsurface.array_deformednormal3f;
3853 rsurface.normal3f_bufferobject = 0;
3854 rsurface.normal3f_bufferoffset = 0;
3856 case Q3DEFORM_AUTOSPRITE2:
3857 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3858 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3859 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3860 VectorNormalize(newforward);
3861 VectorNormalize(newright);
3862 VectorNormalize(newup);
3863 // make deformed versions of only the model vertices used by the specified surfaces
3864 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3866 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3867 const float *v1, *v2;
3877 memset(shortest, 0, sizeof(shortest));
3878 // a single autosprite surface can contain multiple sprites...
3879 for (j = 0;j < surface->num_vertices - 3;j += 4)
3881 VectorClear(center);
3882 for (i = 0;i < 4;i++)
3883 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3884 VectorScale(center, 0.25f, center);
3885 // find the two shortest edges, then use them to define the
3886 // axis vectors for rotating around the central axis
3887 for (i = 0;i < 6;i++)
3889 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3890 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3892 Debug_PolygonBegin(NULL, 0, false, 0);
3893 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
3894 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);
3895 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
3898 l = VectorDistance2(v1, v2);
3899 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
3901 l += (1.0f / 1024.0f);
3902 if (shortest[0].length2 > l || i == 0)
3904 shortest[1] = shortest[0];
3905 shortest[0].length2 = l;
3906 shortest[0].v1 = v1;
3907 shortest[0].v2 = v2;
3909 else if (shortest[1].length2 > l || i == 1)
3911 shortest[1].length2 = l;
3912 shortest[1].v1 = v1;
3913 shortest[1].v2 = v2;
3916 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
3917 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
3919 Debug_PolygonBegin(NULL, 0, false, 0);
3920 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
3921 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);
3922 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
3925 // this calculates the right vector from the shortest edge
3926 // and the up vector from the edge midpoints
3927 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
3928 VectorNormalize(right);
3929 VectorSubtract(end, start, up);
3930 VectorNormalize(up);
3931 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3932 //VectorSubtract(rsurface.modelorg, center, forward);
3933 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
3934 VectorNegate(forward, forward);
3935 VectorReflect(forward, 0, up, forward);
3936 VectorNormalize(forward);
3937 CrossProduct(up, forward, newright);
3938 VectorNormalize(newright);
3940 Debug_PolygonBegin(NULL, 0, false, 0);
3941 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);
3942 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
3943 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3947 Debug_PolygonBegin(NULL, 0, false, 0);
3948 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
3949 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
3950 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3953 // rotate the quad around the up axis vector, this is made
3954 // especially easy by the fact we know the quad is flat,
3955 // so we only have to subtract the center position and
3956 // measure distance along the right vector, and then
3957 // multiply that by the newright vector and add back the
3959 // we also need to subtract the old position to undo the
3960 // displacement from the center, which we do with a
3961 // DotProduct, the subtraction/addition of center is also
3962 // optimized into DotProducts here
3963 l = DotProduct(right, center);
3964 for (i = 0;i < 4;i++)
3966 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3967 f = DotProduct(right, v1) - l;
3968 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3971 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);
3972 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);
3974 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3975 rsurface.vertex3f_bufferobject = 0;
3976 rsurface.vertex3f_bufferoffset = 0;
3977 rsurface.svector3f = rsurface.array_deformedsvector3f;
3978 rsurface.svector3f_bufferobject = 0;
3979 rsurface.svector3f_bufferoffset = 0;
3980 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3981 rsurface.tvector3f_bufferobject = 0;
3982 rsurface.tvector3f_bufferoffset = 0;
3983 rsurface.normal3f = rsurface.array_deformednormal3f;
3984 rsurface.normal3f_bufferobject = 0;
3985 rsurface.normal3f_bufferoffset = 0;
3987 case Q3DEFORM_NORMAL:
3988 // deform the normals to make reflections wavey
3989 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3991 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3992 for (j = 0;j < surface->num_vertices;j++)
3995 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
3996 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
3997 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
3998 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
3999 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4000 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4001 VectorNormalize(normal);
4003 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);
4005 rsurface.svector3f = rsurface.array_deformedsvector3f;
4006 rsurface.svector3f_bufferobject = 0;
4007 rsurface.svector3f_bufferoffset = 0;
4008 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4009 rsurface.tvector3f_bufferobject = 0;
4010 rsurface.tvector3f_bufferoffset = 0;
4011 rsurface.normal3f = rsurface.array_deformednormal3f;
4012 rsurface.normal3f_bufferobject = 0;
4013 rsurface.normal3f_bufferoffset = 0;
4016 // deform vertex array to make wavey water and flags and such
4017 waveparms[0] = deform->waveparms[0];
4018 waveparms[1] = deform->waveparms[1];
4019 waveparms[2] = deform->waveparms[2];
4020 waveparms[3] = deform->waveparms[3];
4021 // this is how a divisor of vertex influence on deformation
4022 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4023 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4024 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4026 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4027 for (j = 0;j < surface->num_vertices;j++)
4029 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4030 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4031 // if the wavefunc depends on time, evaluate it per-vertex
4034 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4035 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4037 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4040 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4041 rsurface.vertex3f_bufferobject = 0;
4042 rsurface.vertex3f_bufferoffset = 0;
4044 case Q3DEFORM_BULGE:
4045 // deform vertex array to make the surface have moving bulges
4046 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4048 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4049 for (j = 0;j < surface->num_vertices;j++)
4051 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4052 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4055 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4056 rsurface.vertex3f_bufferobject = 0;
4057 rsurface.vertex3f_bufferoffset = 0;
4060 // deform vertex array
4061 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4062 VectorScale(deform->parms, scale, waveparms);
4063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4066 for (j = 0;j < surface->num_vertices;j++)
4067 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4069 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4070 rsurface.vertex3f_bufferobject = 0;
4071 rsurface.vertex3f_bufferoffset = 0;
4075 // generate texcoords based on the chosen texcoord source
4076 switch(rsurface.texture->tcgen.tcgen)
4079 case Q3TCGEN_TEXTURE:
4080 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4081 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4082 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4084 case Q3TCGEN_LIGHTMAP:
4085 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4086 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4087 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4089 case Q3TCGEN_VECTOR:
4090 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4092 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4093 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)
4095 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4096 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4099 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4100 rsurface.texcoordtexture2f_bufferobject = 0;
4101 rsurface.texcoordtexture2f_bufferoffset = 0;
4103 case Q3TCGEN_ENVIRONMENT:
4104 // make environment reflections using a spheremap
4105 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4107 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4108 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4109 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4110 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4111 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4113 float l, d, eyedir[3];
4114 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4115 l = 0.5f / VectorLength(eyedir);
4116 d = DotProduct(normal, eyedir)*2;
4117 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4118 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4121 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4122 rsurface.texcoordtexture2f_bufferobject = 0;
4123 rsurface.texcoordtexture2f_bufferoffset = 0;
4126 // the only tcmod that needs software vertex processing is turbulent, so
4127 // check for it here and apply the changes if needed
4128 // and we only support that as the first one
4129 // (handling a mixture of turbulent and other tcmods would be problematic
4130 // without punting it entirely to a software path)
4131 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4133 amplitude = rsurface.texture->tcmods[0].parms[1];
4134 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4135 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4137 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4138 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)
4140 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4141 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4144 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4145 rsurface.texcoordtexture2f_bufferobject = 0;
4146 rsurface.texcoordtexture2f_bufferoffset = 0;
4148 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4149 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4150 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4151 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4154 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4157 const msurface_t *surface = texturesurfacelist[0];
4158 const msurface_t *surface2;
4163 // TODO: lock all array ranges before render, rather than on each surface
4164 if (texturenumsurfaces == 1)
4166 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4167 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4169 else if (r_batchmode.integer == 2)
4171 #define MAXBATCHTRIANGLES 4096
4172 int batchtriangles = 0;
4173 int batchelements[MAXBATCHTRIANGLES*3];
4174 for (i = 0;i < texturenumsurfaces;i = j)
4176 surface = texturesurfacelist[i];
4178 if (surface->num_triangles > MAXBATCHTRIANGLES)
4180 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));
4183 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4184 batchtriangles = surface->num_triangles;
4185 firstvertex = surface->num_firstvertex;
4186 endvertex = surface->num_firstvertex + surface->num_vertices;
4187 for (;j < texturenumsurfaces;j++)
4189 surface2 = texturesurfacelist[j];
4190 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4192 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4193 batchtriangles += surface2->num_triangles;
4194 firstvertex = min(firstvertex, surface2->num_firstvertex);
4195 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4197 surface2 = texturesurfacelist[j-1];
4198 numvertices = endvertex - firstvertex;
4199 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4202 else if (r_batchmode.integer == 1)
4204 for (i = 0;i < texturenumsurfaces;i = j)
4206 surface = texturesurfacelist[i];
4207 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4208 if (texturesurfacelist[j] != surface2)
4210 surface2 = texturesurfacelist[j-1];
4211 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4212 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4213 GL_LockArrays(surface->num_firstvertex, numvertices);
4214 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4219 for (i = 0;i < texturenumsurfaces;i++)
4221 surface = texturesurfacelist[i];
4222 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4223 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));
4228 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4232 const msurface_t *surface = texturesurfacelist[0];
4233 const msurface_t *surface2;
4238 // TODO: lock all array ranges before render, rather than on each surface
4239 if (texturenumsurfaces == 1)
4241 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4242 if (deluxemaptexunit >= 0)
4243 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4244 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4245 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));
4247 else if (r_batchmode.integer == 2)
4249 #define MAXBATCHTRIANGLES 4096
4250 int batchtriangles = 0;
4251 int batchelements[MAXBATCHTRIANGLES*3];
4252 for (i = 0;i < texturenumsurfaces;i = j)
4254 surface = texturesurfacelist[i];
4255 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4256 if (deluxemaptexunit >= 0)
4257 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4259 if (surface->num_triangles > MAXBATCHTRIANGLES)
4261 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));
4264 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4265 batchtriangles = surface->num_triangles;
4266 firstvertex = surface->num_firstvertex;
4267 endvertex = surface->num_firstvertex + surface->num_vertices;
4268 for (;j < texturenumsurfaces;j++)
4270 surface2 = texturesurfacelist[j];
4271 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4273 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4274 batchtriangles += surface2->num_triangles;
4275 firstvertex = min(firstvertex, surface2->num_firstvertex);
4276 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4278 surface2 = texturesurfacelist[j-1];
4279 numvertices = endvertex - firstvertex;
4280 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4283 else if (r_batchmode.integer == 1)
4286 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4287 for (i = 0;i < texturenumsurfaces;i = j)
4289 surface = texturesurfacelist[i];
4290 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4291 if (texturesurfacelist[j] != surface2)
4293 Con_Printf(" %i", j - i);
4296 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4298 for (i = 0;i < texturenumsurfaces;i = j)
4300 surface = texturesurfacelist[i];
4301 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4302 if (deluxemaptexunit >= 0)
4303 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4304 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4305 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4308 Con_Printf(" %i", j - i);
4310 surface2 = texturesurfacelist[j-1];
4311 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4312 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4313 GL_LockArrays(surface->num_firstvertex, numvertices);
4314 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4322 for (i = 0;i < texturenumsurfaces;i++)
4324 surface = texturesurfacelist[i];
4325 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4326 if (deluxemaptexunit >= 0)
4327 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4328 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4329 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));
4334 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4337 int texturesurfaceindex;
4338 if (r_showsurfaces.integer == 2)
4340 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4342 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4343 for (j = 0;j < surface->num_triangles;j++)
4345 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4346 GL_Color(f, f, f, 1);
4347 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)));
4353 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4355 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4356 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4357 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);
4358 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4359 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));
4364 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4366 int texturesurfaceindex;
4370 if (rsurface.lightmapcolor4f)
4372 // generate color arrays for the surfaces in this list
4373 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4375 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4376 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)
4378 f = FogPoint_Model(v);
4388 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4390 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4391 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)
4393 f = FogPoint_Model(v);
4401 rsurface.lightmapcolor4f = rsurface.array_color4f;
4402 rsurface.lightmapcolor4f_bufferobject = 0;
4403 rsurface.lightmapcolor4f_bufferoffset = 0;
4406 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4408 int texturesurfaceindex;
4411 if (!rsurface.lightmapcolor4f)
4413 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4415 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4416 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)
4424 rsurface.lightmapcolor4f = rsurface.array_color4f;
4425 rsurface.lightmapcolor4f_bufferobject = 0;
4426 rsurface.lightmapcolor4f_bufferoffset = 0;
4429 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
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_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4442 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4444 // TODO: optimize applyfog && applycolor case
4445 // just apply fog if necessary, and tint the fog color array if necessary
4446 rsurface.lightmapcolor4f = NULL;
4447 rsurface.lightmapcolor4f_bufferobject = 0;
4448 rsurface.lightmapcolor4f_bufferoffset = 0;
4449 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4450 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4451 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4452 GL_Color(r, g, b, a);
4453 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4456 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4458 int texturesurfaceindex;
4462 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4464 // generate color arrays for the surfaces in this list
4465 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4467 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4468 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4470 if (surface->lightmapinfo->samples)
4472 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4473 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4474 VectorScale(lm, scale, c);
4475 if (surface->lightmapinfo->styles[1] != 255)
4477 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4479 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4480 VectorMA(c, scale, lm, c);
4481 if (surface->lightmapinfo->styles[2] != 255)
4484 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4485 VectorMA(c, scale, lm, c);
4486 if (surface->lightmapinfo->styles[3] != 255)
4489 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4490 VectorMA(c, scale, lm, c);
4500 rsurface.lightmapcolor4f = rsurface.array_color4f;
4501 rsurface.lightmapcolor4f_bufferobject = 0;
4502 rsurface.lightmapcolor4f_bufferoffset = 0;
4506 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4507 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4508 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4510 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4511 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4512 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4513 GL_Color(r, g, b, a);
4514 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4517 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4519 int texturesurfaceindex;
4523 vec3_t ambientcolor;
4524 vec3_t diffusecolor;
4528 VectorCopy(rsurface.modellight_lightdir, lightdir);
4529 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4530 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4531 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4532 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4533 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4534 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4535 if (VectorLength2(diffusecolor) > 0)
4537 // generate color arrays for the surfaces in this list
4538 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4540 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4541 int numverts = surface->num_vertices;
4542 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4543 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4544 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4545 // q3-style directional shading
4546 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4548 if ((f = DotProduct(c2, lightdir)) > 0)
4549 VectorMA(ambientcolor, f, diffusecolor, c);
4551 VectorCopy(ambientcolor, c);
4560 rsurface.lightmapcolor4f = rsurface.array_color4f;
4561 rsurface.lightmapcolor4f_bufferobject = 0;
4562 rsurface.lightmapcolor4f_bufferoffset = 0;
4566 r = ambientcolor[0];
4567 g = ambientcolor[1];
4568 b = ambientcolor[2];
4569 rsurface.lightmapcolor4f = NULL;
4570 rsurface.lightmapcolor4f_bufferobject = 0;
4571 rsurface.lightmapcolor4f_bufferoffset = 0;
4573 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4574 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4575 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4576 GL_Color(r, g, b, a);
4577 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4580 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4582 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4583 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4584 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4585 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4586 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4588 rsurface.mode = RSURFMODE_SHOWSURFACES;
4590 GL_BlendFunc(GL_ONE, GL_ZERO);
4591 R_Mesh_ColorPointer(NULL, 0, 0);
4592 R_Mesh_ResetTextureState();
4594 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4595 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4598 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4600 // transparent sky would be ridiculous
4601 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4603 if (rsurface.mode != RSURFMODE_SKY)
4605 if (rsurface.mode == RSURFMODE_GLSL)
4607 qglUseProgramObjectARB(0);CHECKGLERROR
4609 rsurface.mode = RSURFMODE_SKY;
4613 skyrendernow = false;
4615 // restore entity matrix
4616 R_Mesh_Matrix(&rsurface.matrix);
4618 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4619 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4620 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4621 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4623 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4624 // skymasking on them, and Quake3 never did sky masking (unlike
4625 // software Quake and software Quake2), so disable the sky masking
4626 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4627 // and skymasking also looks very bad when noclipping outside the
4628 // level, so don't use it then either.
4629 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4631 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4632 R_Mesh_ColorPointer(NULL, 0, 0);
4633 R_Mesh_ResetTextureState();
4634 if (skyrendermasked)
4636 // depth-only (masking)
4637 GL_ColorMask(0,0,0,0);
4638 // just to make sure that braindead drivers don't draw
4639 // anything despite that colormask...
4640 GL_BlendFunc(GL_ZERO, GL_ONE);
4645 GL_BlendFunc(GL_ONE, GL_ZERO);
4647 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4648 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4649 if (skyrendermasked)
4650 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4654 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4656 if (rsurface.mode != RSURFMODE_GLSL)
4658 rsurface.mode = RSURFMODE_GLSL;
4659 R_Mesh_ResetTextureState();
4662 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4663 if (!r_glsl_permutation)
4666 if (rsurface.lightmode == 2)
4667 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4669 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4670 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4671 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4672 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4673 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4674 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4676 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]);
4677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
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(NULL, 0, 0);
4684 else if (rsurface.uselightmaptexture)
4686 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4687 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4688 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4689 R_Mesh_ColorPointer(NULL, 0, 0);
4693 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4694 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4695 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4696 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4699 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4700 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4702 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4703 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4708 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4710 // OpenGL 1.3 path - anything not completely ancient
4711 int texturesurfaceindex;
4712 qboolean applycolor;
4716 const texturelayer_t *layer;
4717 if (rsurface.mode != RSURFMODE_MULTIPASS)
4718 rsurface.mode = RSURFMODE_MULTIPASS;
4719 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4720 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4723 int layertexrgbscale;
4724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4726 if (layerindex == 0)
4730 GL_AlphaTest(false);
4731 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4734 GL_DepthMask(layer->depthmask);
4735 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4736 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4738 layertexrgbscale = 4;
4739 VectorScale(layer->color, 0.25f, layercolor);
4741 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4743 layertexrgbscale = 2;
4744 VectorScale(layer->color, 0.5f, layercolor);
4748 layertexrgbscale = 1;
4749 VectorScale(layer->color, 1.0f, layercolor);
4751 layercolor[3] = layer->color[3];
4752 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4753 R_Mesh_ColorPointer(NULL, 0, 0);
4754 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4755 switch (layer->type)
4757 case TEXTURELAYERTYPE_LITTEXTURE:
4758 memset(&m, 0, sizeof(m));
4759 m.tex[0] = R_GetTexture(r_texture_white);
4760 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4761 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4762 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4763 m.tex[1] = R_GetTexture(layer->texture);
4764 m.texmatrix[1] = layer->texmatrix;
4765 m.texrgbscale[1] = layertexrgbscale;
4766 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4767 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4768 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4769 R_Mesh_TextureState(&m);
4770 if (rsurface.lightmode == 2)
4771 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4772 else if (rsurface.uselightmaptexture)
4773 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4775 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4777 case TEXTURELAYERTYPE_TEXTURE:
4778 memset(&m, 0, sizeof(m));
4779 m.tex[0] = R_GetTexture(layer->texture);
4780 m.texmatrix[0] = layer->texmatrix;
4781 m.texrgbscale[0] = layertexrgbscale;
4782 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4783 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4784 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4785 R_Mesh_TextureState(&m);
4786 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4788 case TEXTURELAYERTYPE_FOG:
4789 memset(&m, 0, sizeof(m));
4790 m.texrgbscale[0] = layertexrgbscale;
4793 m.tex[0] = R_GetTexture(layer->texture);
4794 m.texmatrix[0] = layer->texmatrix;
4795 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4796 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4797 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4799 R_Mesh_TextureState(&m);
4800 // generate a color array for the fog pass
4801 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4802 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4806 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4807 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)
4809 f = 1 - FogPoint_Model(v);
4810 c[0] = layercolor[0];
4811 c[1] = layercolor[1];
4812 c[2] = layercolor[2];
4813 c[3] = f * layercolor[3];
4816 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4819 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4821 GL_LockArrays(0, 0);
4824 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4826 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4827 GL_AlphaTest(false);
4831 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4833 // OpenGL 1.1 - crusty old voodoo path
4834 int texturesurfaceindex;
4838 const texturelayer_t *layer;
4839 if (rsurface.mode != RSURFMODE_MULTIPASS)
4840 rsurface.mode = RSURFMODE_MULTIPASS;
4841 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4842 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4844 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4846 if (layerindex == 0)
4850 GL_AlphaTest(false);
4851 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4854 GL_DepthMask(layer->depthmask);
4855 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4856 R_Mesh_ColorPointer(NULL, 0, 0);
4857 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4858 switch (layer->type)
4860 case TEXTURELAYERTYPE_LITTEXTURE:
4861 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4863 // two-pass lit texture with 2x rgbscale
4864 // first the lightmap pass
4865 memset(&m, 0, sizeof(m));
4866 m.tex[0] = R_GetTexture(r_texture_white);
4867 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4868 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4869 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4870 R_Mesh_TextureState(&m);
4871 if (rsurface.lightmode == 2)
4872 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4873 else if (rsurface.uselightmaptexture)
4874 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4876 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4877 GL_LockArrays(0, 0);
4878 // then apply the texture to it
4879 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4880 memset(&m, 0, sizeof(m));
4881 m.tex[0] = R_GetTexture(layer->texture);
4882 m.texmatrix[0] = layer->texmatrix;
4883 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4884 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4885 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4886 R_Mesh_TextureState(&m);
4887 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);
4891 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4892 memset(&m, 0, sizeof(m));
4893 m.tex[0] = R_GetTexture(layer->texture);
4894 m.texmatrix[0] = layer->texmatrix;
4895 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4896 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4897 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4898 R_Mesh_TextureState(&m);
4899 if (rsurface.lightmode == 2)
4900 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);
4902 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);
4905 case TEXTURELAYERTYPE_TEXTURE:
4906 // singletexture unlit texture with transparency support
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);
4914 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);
4916 case TEXTURELAYERTYPE_FOG:
4917 // singletexture fogging
4918 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4921 memset(&m, 0, sizeof(m));
4922 m.tex[0] = R_GetTexture(layer->texture);
4923 m.texmatrix[0] = layer->texmatrix;
4924 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4925 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4926 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4927 R_Mesh_TextureState(&m);
4930 R_Mesh_ResetTextureState();
4931 // generate a color array for the fog pass
4932 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4936 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4937 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)
4939 f = 1 - FogPoint_Model(v);
4940 c[0] = layer->color[0];
4941 c[1] = layer->color[1];
4942 c[2] = layer->color[2];
4943 c[3] = f * layer->color[3];
4946 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4949 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4951 GL_LockArrays(0, 0);
4954 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4956 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4957 GL_AlphaTest(false);
4961 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4963 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4965 rsurface.rtlight = NULL;
4969 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4971 if (rsurface.mode != RSURFMODE_MULTIPASS)
4972 rsurface.mode = RSURFMODE_MULTIPASS;
4973 if (r_depthfirst.integer == 3)
4975 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4976 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4980 GL_ColorMask(0,0,0,0);
4983 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4984 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4985 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4987 GL_BlendFunc(GL_ONE, GL_ZERO);
4989 GL_AlphaTest(false);
4990 R_Mesh_ColorPointer(NULL, 0, 0);
4991 R_Mesh_ResetTextureState();
4992 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4993 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4994 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4995 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4997 else if (r_depthfirst.integer == 3)
4999 else if (r_showsurfaces.integer)
5001 if (rsurface.mode != RSURFMODE_MULTIPASS)
5002 rsurface.mode = RSURFMODE_MULTIPASS;
5003 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5004 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5006 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5007 GL_BlendFunc(GL_ONE, GL_ZERO);
5008 GL_DepthMask(writedepth);
5010 GL_AlphaTest(false);
5011 R_Mesh_ColorPointer(NULL, 0, 0);
5012 R_Mesh_ResetTextureState();
5013 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5014 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5015 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5017 else if (gl_lightmaps.integer)
5020 if (rsurface.mode != RSURFMODE_MULTIPASS)
5021 rsurface.mode = RSURFMODE_MULTIPASS;
5022 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5024 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5025 GL_BlendFunc(GL_ONE, GL_ZERO);
5026 GL_DepthMask(writedepth);
5028 GL_AlphaTest(false);
5029 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5030 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5031 R_Mesh_ColorPointer(NULL, 0, 0);
5032 memset(&m, 0, sizeof(m));
5033 m.tex[0] = R_GetTexture(r_texture_white);
5034 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5035 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5036 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5037 R_Mesh_TextureState(&m);
5038 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5039 if (rsurface.lightmode == 2)
5040 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5041 else if (rsurface.uselightmaptexture)
5042 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5044 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5045 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5047 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5049 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5050 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5052 else if (rsurface.texture->currentnumlayers)
5054 // write depth for anything we skipped on the depth-only pass earlier
5055 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5057 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5058 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5059 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5060 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5061 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5062 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5063 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5064 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5065 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5066 if (r_glsl.integer && gl_support_fragment_shader)
5067 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5068 else if (gl_combine.integer && r_textureunits.integer >= 2)
5069 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5071 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5072 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5075 GL_LockArrays(0, 0);
5078 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5081 int texturenumsurfaces, endsurface;
5083 msurface_t *surface;
5084 msurface_t *texturesurfacelist[1024];
5086 // if the model is static it doesn't matter what value we give for
5087 // wantnormals and wanttangents, so this logic uses only rules applicable
5088 // to a model, knowing that they are meaningless otherwise
5089 if (ent == r_refdef.worldentity)
5090 RSurf_ActiveWorldEntity();
5091 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5092 RSurf_ActiveModelEntity(ent, false, false);
5094 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5096 for (i = 0;i < numsurfaces;i = j)
5099 surface = rsurface.modelsurfaces + surfacelist[i];
5100 texture = surface->texture;
5101 R_UpdateTextureInfo(ent, texture);
5102 rsurface.texture = texture->currentframe;
5103 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5104 // scan ahead until we find a different texture
5105 endsurface = min(i + 1024, numsurfaces);
5106 texturenumsurfaces = 0;
5107 texturesurfacelist[texturenumsurfaces++] = surface;
5108 for (;j < endsurface;j++)
5110 surface = rsurface.modelsurfaces + surfacelist[j];
5111 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5113 texturesurfacelist[texturenumsurfaces++] = surface;
5115 // render the range of surfaces
5116 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5122 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5125 vec3_t tempcenter, center;
5127 // break the surface list down into batches by texture and use of lightmapping
5128 for (i = 0;i < numsurfaces;i = j)
5131 // texture is the base texture pointer, rsurface.texture is the
5132 // current frame/skin the texture is directing us to use (for example
5133 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5134 // use skin 1 instead)
5135 texture = surfacelist[i]->texture;
5136 rsurface.texture = texture->currentframe;
5137 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5138 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5140 // if this texture is not the kind we want, skip ahead to the next one
5141 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5145 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5147 // transparent surfaces get pushed off into the transparent queue
5148 const msurface_t *surface = surfacelist[i];
5151 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5152 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5153 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5154 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5155 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5159 // simply scan ahead until we find a different texture or lightmap state
5160 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5162 // render the range of surfaces
5163 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5168 float locboxvertex3f[6*4*3] =
5170 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5171 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5172 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5173 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5174 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5175 1,0,0, 0,0,0, 0,1,0, 1,1,0
5178 int locboxelement3i[6*2*3] =
5188 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5191 cl_locnode_t *loc = (cl_locnode_t *)ent;
5193 float vertex3f[6*4*3];
5195 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5196 GL_DepthMask(false);
5197 GL_DepthRange(0, 1);
5198 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5200 GL_CullFace(GL_NONE);
5201 R_Mesh_Matrix(&identitymatrix);
5203 R_Mesh_VertexPointer(vertex3f, 0, 0);
5204 R_Mesh_ColorPointer(NULL, 0, 0);
5205 R_Mesh_ResetTextureState();
5208 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5209 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5210 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5211 surfacelist[0] < 0 ? 0.5f : 0.125f);
5213 if (VectorCompare(loc->mins, loc->maxs))
5215 VectorSet(size, 2, 2, 2);
5216 VectorMA(loc->mins, -0.5f, size, mins);
5220 VectorCopy(loc->mins, mins);
5221 VectorSubtract(loc->maxs, loc->mins, size);
5224 for (i = 0;i < 6*4*3;)
5225 for (j = 0;j < 3;j++, i++)
5226 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5228 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5231 void R_DrawLocs(void)
5234 cl_locnode_t *loc, *nearestloc;
5236 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5237 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5239 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5240 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5244 void R_DrawCollisionBrushes(entity_render_t *ent)
5248 msurface_t *surface;
5249 model_t *model = ent->model;
5250 if (!model->brush.num_brushes)
5253 R_Mesh_ColorPointer(NULL, 0, 0);
5254 R_Mesh_ResetTextureState();
5255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5256 GL_DepthMask(false);
5257 GL_DepthRange(0, 1);
5258 GL_DepthTest(!r_showdisabledepthtest.integer);
5259 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5260 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5261 if (brush->colbrushf && brush->colbrushf->numtriangles)
5262 R_DrawCollisionBrush(brush->colbrushf);
5263 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5264 if (surface->num_collisiontriangles)
5265 R_DrawCollisionSurface(ent, surface);
5266 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5269 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5272 const int *elements;
5273 msurface_t *surface;
5274 model_t *model = ent->model;
5277 GL_DepthRange(0, 1);
5278 GL_DepthTest(!r_showdisabledepthtest.integer);
5279 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5281 GL_BlendFunc(GL_ONE, GL_ZERO);
5282 R_Mesh_ColorPointer(NULL, 0, 0);
5283 R_Mesh_ResetTextureState();
5284 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5286 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5288 rsurface.texture = surface->texture->currentframe;
5289 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5291 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5294 if (!rsurface.texture->currentlayers->depthmask)
5295 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5296 else if (ent == r_refdef.worldentity)
5297 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5299 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5300 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5303 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5305 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5306 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5307 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5308 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5315 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5317 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5319 VectorCopy(rsurface.vertex3f + l * 3, v);
5320 qglVertex3f(v[0], v[1], v[2]);
5321 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5322 qglVertex3f(v[0], v[1], v[2]);
5326 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5328 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5330 VectorCopy(rsurface.vertex3f + l * 3, v);
5331 qglVertex3f(v[0], v[1], v[2]);
5332 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5333 qglVertex3f(v[0], v[1], v[2]);
5337 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5339 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5341 VectorCopy(rsurface.vertex3f + l * 3, v);
5342 qglVertex3f(v[0], v[1], v[2]);
5343 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5344 qglVertex3f(v[0], v[1], v[2]);
5351 rsurface.texture = NULL;
5354 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5355 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5357 int i, j, endj, f, flagsmask;
5358 int counttriangles = 0;
5359 msurface_t *surface, **surfacechain;
5361 model_t *model = r_refdef.worldmodel;
5362 const int maxsurfacelist = 1024;
5363 int numsurfacelist = 0;
5364 msurface_t *surfacelist[1024];
5368 RSurf_ActiveWorldEntity();
5370 // update light styles
5371 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5373 for (i = 0;i < model->brushq1.light_styles;i++)
5375 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5377 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5378 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5379 for (;(surface = *surfacechain);surfacechain++)
5380 surface->cached_dlight = true;
5385 R_UpdateAllTextureInfo(r_refdef.worldentity);
5386 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5389 rsurface.uselightmaptexture = false;
5390 rsurface.texture = NULL;
5392 j = model->firstmodelsurface;
5393 endj = j + model->nummodelsurfaces;
5396 // quickly skip over non-visible surfaces
5397 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5399 // quickly iterate over visible surfaces
5400 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5402 // process this surface
5403 surface = model->data_surfaces + j;
5404 // if this surface fits the criteria, add it to the list
5405 if (surface->num_triangles)
5407 // if lightmap parameters changed, rebuild lightmap texture
5408 if (surface->cached_dlight)
5409 R_BuildLightMap(r_refdef.worldentity, surface);
5410 // add face to draw list
5411 surfacelist[numsurfacelist++] = surface;
5412 counttriangles += surface->num_triangles;
5413 if (numsurfacelist >= maxsurfacelist)
5415 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5422 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5423 r_refdef.stats.entities_triangles += counttriangles;
5426 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5427 R_DrawCollisionBrushes(r_refdef.worldentity);
5429 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5430 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5433 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5435 int i, f, flagsmask;
5436 int counttriangles = 0;
5437 msurface_t *surface, *endsurface, **surfacechain;
5439 model_t *model = ent->model;
5440 const int maxsurfacelist = 1024;
5441 int numsurfacelist = 0;
5442 msurface_t *surfacelist[1024];
5446 // if the model is static it doesn't matter what value we give for
5447 // wantnormals and wanttangents, so this logic uses only rules applicable
5448 // to a model, knowing that they are meaningless otherwise
5449 if (ent == r_refdef.worldentity)
5450 RSurf_ActiveWorldEntity();
5451 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5452 RSurf_ActiveModelEntity(ent, false, false);
5454 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5456 // update light styles
5457 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5459 for (i = 0;i < model->brushq1.light_styles;i++)
5461 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5463 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5464 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5465 for (;(surface = *surfacechain);surfacechain++)
5466 surface->cached_dlight = true;
5471 R_UpdateAllTextureInfo(ent);
5472 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5475 rsurface.uselightmaptexture = false;
5476 rsurface.texture = NULL;
5478 surface = model->data_surfaces + model->firstmodelsurface;
5479 endsurface = surface + model->nummodelsurfaces;
5480 for (;surface < endsurface;surface++)
5482 // if this surface fits the criteria, add it to the list
5483 if (surface->num_triangles)
5485 // if lightmap parameters changed, rebuild lightmap texture
5486 if (surface->cached_dlight)
5487 R_BuildLightMap(ent, surface);
5488 // add face to draw list
5489 surfacelist[numsurfacelist++] = surface;
5490 counttriangles += surface->num_triangles;
5491 if (numsurfacelist >= maxsurfacelist)
5493 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5499 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5500 r_refdef.stats.entities_triangles += counttriangles;
5503 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5504 R_DrawCollisionBrushes(ent);
5506 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5507 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);