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_grey128;
147 rtexture_t *r_texture_black;
148 rtexture_t *r_texture_notexture;
149 rtexture_t *r_texture_whitecube;
150 rtexture_t *r_texture_normalizationcube;
151 rtexture_t *r_texture_fogattenuation;
152 //rtexture_t *r_texture_fogintensity;
154 // information about each possible shader permutation
155 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
156 // currently selected permutation
157 r_glsl_permutation_t *r_glsl_permutation;
159 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
160 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
162 // vertex coordinates for a quad that covers the screen exactly
163 const static float r_screenvertex3f[12] =
171 extern void R_DrawModelShadows(void);
173 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
176 for (i = 0;i < verts;i++)
187 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
190 for (i = 0;i < verts;i++)
200 // FIXME: move this to client?
203 if (gamemode == GAME_NEHAHRA)
205 Cvar_Set("gl_fogenable", "0");
206 Cvar_Set("gl_fogdensity", "0.2");
207 Cvar_Set("gl_fogred", "0.3");
208 Cvar_Set("gl_foggreen", "0.3");
209 Cvar_Set("gl_fogblue", "0.3");
211 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
214 float FogPoint_World(const vec3_t p)
216 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
217 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
220 float FogPoint_Model(const vec3_t p)
222 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
223 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
226 static void R_BuildBlankTextures(void)
228 unsigned char data[4];
229 data[0] = 128; // normal X
230 data[1] = 128; // normal Y
231 data[2] = 255; // normal Z
232 data[3] = 128; // height
233 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
238 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
243 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
248 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
251 static void R_BuildNoTexture(void)
254 unsigned char pix[16][16][4];
255 // this makes a light grey/dark grey checkerboard texture
256 for (y = 0;y < 16;y++)
258 for (x = 0;x < 16;x++)
260 if ((y < 8) ^ (x < 8))
276 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
279 static void R_BuildWhiteCube(void)
281 unsigned char data[6*1*1*4];
282 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
283 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
284 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
285 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
286 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
287 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
288 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
291 static void R_BuildNormalizationCube(void)
295 vec_t s, t, intensity;
297 unsigned char data[6][NORMSIZE][NORMSIZE][4];
298 for (side = 0;side < 6;side++)
300 for (y = 0;y < NORMSIZE;y++)
302 for (x = 0;x < NORMSIZE;x++)
304 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
305 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
340 intensity = 127.0f / sqrt(DotProduct(v, v));
341 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
342 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
343 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
344 data[side][y][x][3] = 255;
348 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
351 static void R_BuildFogTexture(void)
355 unsigned char data1[FOGWIDTH][4];
356 //unsigned char data2[FOGWIDTH][4];
357 for (x = 0;x < FOGWIDTH;x++)
359 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
364 //data2[x][0] = 255 - b;
365 //data2[x][1] = 255 - b;
366 //data2[x][2] = 255 - b;
369 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
370 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
373 static const char *builtinshaderstring =
374 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
375 "// written by Forest 'LordHavoc' Hale\n"
377 "// common definitions between vertex shader and fragment shader:\n"
379 "#ifdef __GLSL_CG_DATA_TYPES\n"
380 "#define myhalf half\n"
381 "#define myhvec2 hvec2\n"
382 "#define myhvec3 hvec3\n"
383 "#define myhvec4 hvec4\n"
385 "#define myhalf float\n"
386 "#define myhvec2 vec2\n"
387 "#define myhvec3 vec3\n"
388 "#define myhvec4 vec4\n"
391 "varying vec2 TexCoord;\n"
392 "varying vec2 TexCoordLightmap;\n"
394 "varying vec3 CubeVector;\n"
395 "varying vec3 LightVector;\n"
396 "varying vec3 EyeVector;\n"
398 "varying vec3 EyeVectorModelSpace;\n"
401 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
402 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
403 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
408 "// vertex shader specific:\n"
409 "#ifdef VERTEX_SHADER\n"
411 "uniform vec3 LightPosition;\n"
412 "uniform vec3 EyePosition;\n"
413 "uniform vec3 LightDir;\n"
415 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
419 " gl_FrontColor = gl_Color;\n"
420 " // copy the surface texcoord\n"
421 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
422 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
423 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
426 "#ifdef MODE_LIGHTSOURCE\n"
427 " // transform vertex position into light attenuation/cubemap space\n"
428 " // (-1 to +1 across the light box)\n"
429 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
431 " // transform unnormalized light direction into tangent space\n"
432 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
433 " // normalize it per pixel)\n"
434 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
435 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
436 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
437 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
440 "#ifdef MODE_LIGHTDIRECTION\n"
441 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
442 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
443 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
446 " // transform unnormalized eye direction into tangent space\n"
448 " vec3 EyeVectorModelSpace;\n"
450 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
451 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
452 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
453 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
455 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
456 " VectorS = gl_MultiTexCoord1.xyz;\n"
457 " VectorT = gl_MultiTexCoord2.xyz;\n"
458 " VectorR = gl_MultiTexCoord3.xyz;\n"
461 " // transform vertex to camera space, using ftransform to match non-VS\n"
463 " gl_Position = ftransform();\n"
466 "#endif // VERTEX_SHADER\n"
471 "// fragment shader specific:\n"
472 "#ifdef FRAGMENT_SHADER\n"
474 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
475 "uniform sampler2D Texture_Normal;\n"
476 "uniform sampler2D Texture_Color;\n"
477 "uniform sampler2D Texture_Gloss;\n"
478 "uniform samplerCube Texture_Cube;\n"
479 "uniform sampler2D Texture_Attenuation;\n"
480 "uniform sampler2D Texture_FogMask;\n"
481 "uniform sampler2D Texture_Pants;\n"
482 "uniform sampler2D Texture_Shirt;\n"
483 "uniform sampler2D Texture_Lightmap;\n"
484 "uniform sampler2D Texture_Deluxemap;\n"
485 "uniform sampler2D Texture_Glow;\n"
487 "uniform myhvec3 LightColor;\n"
488 "uniform myhvec3 AmbientColor;\n"
489 "uniform myhvec3 DiffuseColor;\n"
490 "uniform myhvec3 SpecularColor;\n"
491 "uniform myhvec3 Color_Pants;\n"
492 "uniform myhvec3 Color_Shirt;\n"
493 "uniform myhvec3 FogColor;\n"
495 "uniform myhalf GlowScale;\n"
496 "uniform myhalf SceneBrightness;\n"
497 "#ifdef USECONTRASTBOOST\n"
498 "uniform myhalf ContrastBoostCoeff;\n"
501 "uniform float OffsetMapping_Scale;\n"
502 "uniform float OffsetMapping_Bias;\n"
503 "uniform float FogRangeRecip;\n"
505 "uniform myhalf AmbientScale;\n"
506 "uniform myhalf DiffuseScale;\n"
507 "uniform myhalf SpecularScale;\n"
508 "uniform myhalf SpecularPower;\n"
510 "#ifdef USEOFFSETMAPPING\n"
511 "vec2 OffsetMapping(vec2 TexCoord)\n"
513 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
514 " // 14 sample relief mapping: linear search and then binary search\n"
515 " // this basically steps forward a small amount repeatedly until it finds\n"
516 " // itself inside solid, then jitters forward and back using decreasing\n"
517 " // amounts to find the impact\n"
518 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
519 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
520 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
521 " vec3 RT = vec3(TexCoord, 1);\n"
522 " OffsetVector *= 0.1;\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);\n"
527 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
528 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
529 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
530 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
531 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
532 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
533 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
534 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
535 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
536 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
539 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
540 " // this basically moves forward the full distance, and then backs up based\n"
541 " // on height of samples\n"
542 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
543 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
544 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
545 " TexCoord += OffsetVector;\n"
546 " OffsetVector *= 0.333;\n"
547 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
548 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
549 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
550 " return TexCoord;\n"
557 "#ifdef USEOFFSETMAPPING\n"
558 " // apply offsetmapping\n"
559 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
560 "#define TexCoord TexCoordOffset\n"
563 " // combine the diffuse textures (base, pants, shirt)\n"
564 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
565 "#ifdef USECOLORMAPPING\n"
566 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
572 "#ifdef MODE_LIGHTSOURCE\n"
575 " // calculate surface normal, light normal, and specular normal\n"
576 " // compute color intensity for the two textures (colormap and glossmap)\n"
577 " // scale by light color and attenuation as efficiently as possible\n"
578 " // (do as much scalar math as possible rather than vector math)\n"
579 "#ifdef USESPECULAR\n"
580 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
581 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
582 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
584 " // calculate directional shading\n"
585 " 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"
587 "#ifdef USEDIFFUSE\n"
588 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
589 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
591 " // calculate directional shading\n"
592 " 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"
594 " // calculate directionless shading\n"
595 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
599 "#ifdef USECUBEFILTER\n"
600 " // apply light cubemap filter\n"
601 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
602 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
608 "#elif defined(MODE_LIGHTDIRECTION)\n"
609 " // directional model lighting\n"
611 " // get the surface normal and light normal\n"
612 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
613 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
615 " // calculate directional shading\n"
616 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
617 "#ifdef USESPECULAR\n"
618 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
619 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
625 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
626 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
628 " // get the surface normal and light normal\n"
629 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
631 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
632 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
633 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
635 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
637 " // calculate directional shading\n"
638 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
639 "#ifdef USESPECULAR\n"
640 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
641 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
644 " // apply lightmap color\n"
645 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
648 "#else // MODE none (lightmap)\n"
649 " // apply lightmap color\n"
650 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
653 " color *= myhvec4(gl_Color);\n"
656 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
661 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
664 "#ifdef USECONTRASTBOOST\n"
665 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
667 " color.rgb *= SceneBrightness;\n"
670 " gl_FragColor = vec4(color);\n"
673 "#endif // FRAGMENT_SHADER\n"
676 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
677 const char *permutationinfo[][2] =
679 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
680 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
681 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
682 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
683 {"#define USEGLOW\n", " glow"},
684 {"#define USEFOG\n", " fog"},
685 {"#define USECOLORMAPPING\n", " colormapping"},
686 {"#define USEDIFFUSE\n", " diffuse"},
687 {"#define USECONTRASTBOOST\n", " contrastboost"},
688 {"#define USESPECULAR\n", " specular"},
689 {"#define USECUBEFILTER\n", " cubefilter"},
690 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
691 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
695 void R_GLSL_CompilePermutation(const char *filename, int permutation)
698 qboolean shaderfound;
699 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
700 int vertstrings_count;
701 int geomstrings_count;
702 int fragstrings_count;
704 const char *vertstrings_list[32+1];
705 const char *geomstrings_list[32+1];
706 const char *fragstrings_list[32+1];
707 char permutationname[256];
712 vertstrings_list[0] = "#define VERTEX_SHADER\n";
713 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
714 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
715 vertstrings_count = 1;
716 geomstrings_count = 1;
717 fragstrings_count = 1;
718 permutationname[0] = 0;
719 for (i = 0;permutationinfo[i][0];i++)
721 if (permutation & (1<<i))
723 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
724 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
725 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
726 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
730 // keep line numbers correct
731 vertstrings_list[vertstrings_count++] = "\n";
732 geomstrings_list[geomstrings_count++] = "\n";
733 fragstrings_list[fragstrings_count++] = "\n";
736 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
740 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
741 vertstrings_list[vertstrings_count++] = shaderstring;
742 geomstrings_list[geomstrings_count++] = shaderstring;
743 fragstrings_list[fragstrings_count++] = shaderstring;
746 else if (!strcmp(filename, "glsl/default.glsl"))
748 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
749 vertstrings_list[vertstrings_count++] = builtinshaderstring;
750 geomstrings_list[geomstrings_count++] = builtinshaderstring;
751 fragstrings_list[fragstrings_count++] = builtinshaderstring;
754 // clear any lists that are not needed by this shader
755 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
756 vertstrings_count = 0;
757 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
758 geomstrings_count = 0;
759 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
760 fragstrings_count = 0;
761 // compile the shader program
762 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
763 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
767 qglUseProgramObjectARB(p->program);CHECKGLERROR
768 // look up all the uniform variable names we care about, so we don't
769 // have to look them up every time we set them
770 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
771 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
772 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
773 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
774 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
775 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
776 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
777 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
778 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
779 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
780 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
781 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
782 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
783 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
784 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
785 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
786 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
787 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
788 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
789 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
790 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
791 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
792 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
793 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
794 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
795 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
796 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
797 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
798 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
799 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
800 // initialize the samplers to refer to the texture units we use
801 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
802 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
803 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
804 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
805 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
806 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
807 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
808 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
809 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
810 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
811 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
813 qglUseProgramObjectARB(0);CHECKGLERROR
816 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
818 Mem_Free(shaderstring);
821 void R_GLSL_Restart_f(void)
824 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
825 if (r_glsl_permutations[i].program)
826 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
827 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
830 void R_GLSL_DumpShader_f(void)
834 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
837 Con_Printf("failed to write to glsl/default.glsl\n");
841 FS_Print(file, "// The engine may define the following macros:\n");
842 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
843 for (i = 0;permutationinfo[i][0];i++)
844 FS_Printf(file, "// %s", permutationinfo[i][0]);
845 FS_Print(file, "\n");
846 FS_Print(file, builtinshaderstring);
849 Con_Printf("glsl/default.glsl written\n");
852 extern rtexture_t *r_shadow_attenuationgradienttexture;
853 extern rtexture_t *r_shadow_attenuation2dtexture;
854 extern rtexture_t *r_shadow_attenuation3dtexture;
855 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
857 // select a permutation of the lighting shader appropriate to this
858 // combination of texture, entity, light source, and fogging, only use the
859 // minimum features necessary to avoid wasting rendering time in the
860 // fragment shader on features that are not being used
861 const char *shaderfilename = NULL;
862 unsigned int permutation = 0;
864 r_glsl_permutation = NULL;
865 // TODO: implement geometry-shader based shadow volumes someday
866 if (rsurface.rtlight)
869 shaderfilename = "glsl/default.glsl";
870 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
871 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
872 permutation |= SHADERPERMUTATION_CUBEFILTER;
873 if (diffusescale > 0)
874 permutation |= SHADERPERMUTATION_DIFFUSE;
875 if (specularscale > 0)
876 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
877 if (r_refdef.fogenabled)
878 permutation |= SHADERPERMUTATION_FOG;
879 if (rsurface.texture->colormapping)
880 permutation |= SHADERPERMUTATION_COLORMAPPING;
881 if (r_glsl_offsetmapping.integer)
883 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
884 if (r_glsl_offsetmapping_reliefmapping.integer)
885 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
887 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
888 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
890 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
892 // bright unshaded geometry
893 shaderfilename = "glsl/default.glsl";
894 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
895 if (rsurface.texture->currentskinframe->glow)
896 permutation |= SHADERPERMUTATION_GLOW;
897 if (r_refdef.fogenabled)
898 permutation |= SHADERPERMUTATION_FOG;
899 if (rsurface.texture->colormapping)
900 permutation |= SHADERPERMUTATION_COLORMAPPING;
901 if (r_glsl_offsetmapping.integer)
903 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
904 if (r_glsl_offsetmapping_reliefmapping.integer)
905 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
907 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
908 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
910 else if (modellighting)
912 // directional model lighting
913 shaderfilename = "glsl/default.glsl";
914 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
915 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
916 if (rsurface.texture->currentskinframe->glow)
917 permutation |= SHADERPERMUTATION_GLOW;
918 if (specularscale > 0)
919 permutation |= SHADERPERMUTATION_SPECULAR;
920 if (r_refdef.fogenabled)
921 permutation |= SHADERPERMUTATION_FOG;
922 if (rsurface.texture->colormapping)
923 permutation |= SHADERPERMUTATION_COLORMAPPING;
924 if (r_glsl_offsetmapping.integer)
926 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
927 if (r_glsl_offsetmapping_reliefmapping.integer)
928 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
930 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
931 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
936 shaderfilename = "glsl/default.glsl";
937 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
938 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
940 // deluxemapping (light direction texture)
941 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
942 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
944 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
945 if (specularscale > 0)
946 permutation |= SHADERPERMUTATION_SPECULAR;
948 else if (r_glsl_deluxemapping.integer >= 2)
950 // fake deluxemapping (uniform light direction in tangentspace)
951 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
952 if (specularscale > 0)
953 permutation |= SHADERPERMUTATION_SPECULAR;
957 // ordinary lightmapping
960 if (rsurface.texture->currentskinframe->glow)
961 permutation |= SHADERPERMUTATION_GLOW;
962 if (r_refdef.fogenabled)
963 permutation |= SHADERPERMUTATION_FOG;
964 if (rsurface.texture->colormapping)
965 permutation |= SHADERPERMUTATION_COLORMAPPING;
966 if (r_glsl_offsetmapping.integer)
968 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
969 if (r_glsl_offsetmapping_reliefmapping.integer)
970 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
972 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
973 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
975 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
977 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
978 R_GLSL_CompilePermutation(shaderfilename, permutation);
979 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
981 // remove features until we find a valid permutation
983 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
986 return 0; // no bit left to clear
987 // reduce i more quickly whenever it would not remove any bits
988 if (!(permutation & i))
991 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
992 R_GLSL_CompilePermutation(shaderfilename, permutation);
993 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
998 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1000 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1001 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1002 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1004 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1005 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1006 if (permutation & SHADERPERMUTATION_DIFFUSE)
1008 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1009 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1010 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1011 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1015 // ambient only is simpler
1016 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1017 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1018 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1019 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1022 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1024 if (r_glsl_permutation->loc_AmbientColor >= 0)
1025 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1026 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1027 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1028 if (r_glsl_permutation->loc_SpecularColor >= 0)
1029 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1030 if (r_glsl_permutation->loc_LightDir >= 0)
1031 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1035 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1036 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1037 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1039 nmap = rsurface.texture->currentskinframe->nmap;
1040 if (gl_lightmaps.integer)
1041 nmap = r_texture_blanknormalmap;
1042 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1043 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1044 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1045 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1046 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1047 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1048 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1049 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1050 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1051 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1052 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1053 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1054 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1056 // The formula used is actually:
1057 // color.rgb *= SceneBrightness;
1058 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1059 // I simplify that to
1060 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1061 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1063 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1064 // and do [[calculations]] here in the engine
1065 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1066 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1069 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1070 if (r_glsl_permutation->loc_FogColor >= 0)
1072 // additive passes are only darkened by fog, not tinted
1073 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1074 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1076 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1078 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1079 if (r_glsl_permutation->loc_Color_Pants >= 0)
1081 if (rsurface.texture->currentskinframe->pants)
1082 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1084 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1086 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1088 if (rsurface.texture->currentskinframe->shirt)
1089 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1091 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1093 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1094 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1095 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1100 void R_SwitchSurfaceShader(int permutation)
1102 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1104 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1106 qglUseProgramObjectARB(r_glsl_permutation->program);
1111 #define SKINFRAME_HASH 1024
1115 int loadsequence; // incremented each level change
1116 memexpandablearray_t array;
1117 skinframe_t *hash[SKINFRAME_HASH];
1121 void R_SkinFrame_PrepareForPurge(void)
1123 r_skinframe.loadsequence++;
1124 // wrap it without hitting zero
1125 if (r_skinframe.loadsequence >= 200)
1126 r_skinframe.loadsequence = 1;
1129 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1133 // mark the skinframe as used for the purging code
1134 skinframe->loadsequence = r_skinframe.loadsequence;
1137 void R_SkinFrame_Purge(void)
1141 for (i = 0;i < SKINFRAME_HASH;i++)
1143 for (s = r_skinframe.hash[i];s;s = s->next)
1145 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1147 if (s->base == r_texture_notexture) s->base = NULL;
1148 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1149 if (s->merged == s->base) s->merged = NULL;
1150 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1151 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1152 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1153 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1154 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1155 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1156 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1157 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1158 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1159 s->loadsequence = 0;
1165 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1169 char basename[MAX_QPATH];
1171 Image_StripImageExtension(name, basename, sizeof(basename));
1173 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1174 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1175 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1181 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1182 memset(item, 0, sizeof(*item));
1183 strlcpy(item->basename, basename, sizeof(item->basename));
1184 item->textureflags = textureflags;
1185 item->comparewidth = comparewidth;
1186 item->compareheight = compareheight;
1187 item->comparecrc = comparecrc;
1188 item->next = r_skinframe.hash[hashindex];
1189 r_skinframe.hash[hashindex] = item;
1191 R_SkinFrame_MarkUsed(item);
1195 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1197 // FIXME: it should be possible to disable loading various layers using
1198 // cvars, to prevent wasted loading time and memory usage if the user does
1200 qboolean loadnormalmap = true;
1201 qboolean loadgloss = true;
1202 qboolean loadpantsandshirt = true;
1203 qboolean loadglow = true;
1205 unsigned char *pixels;
1206 unsigned char *bumppixels;
1207 unsigned char *basepixels = NULL;
1208 int basepixels_width;
1209 int basepixels_height;
1210 skinframe_t *skinframe;
1212 if (cls.state == ca_dedicated)
1215 // return an existing skinframe if already loaded
1216 // if loading of the first image fails, don't make a new skinframe as it
1217 // would cause all future lookups of this to be missing
1218 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1219 if (skinframe && skinframe->base)
1222 basepixels = loadimagepixels(name, complain, 0, 0);
1223 if (basepixels == NULL)
1226 // we've got some pixels to store, so really allocate this new texture now
1228 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1229 skinframe->stain = NULL;
1230 skinframe->merged = NULL;
1231 skinframe->base = r_texture_notexture;
1232 skinframe->pants = NULL;
1233 skinframe->shirt = NULL;
1234 skinframe->nmap = r_texture_blanknormalmap;
1235 skinframe->gloss = NULL;
1236 skinframe->glow = NULL;
1237 skinframe->fog = NULL;
1239 basepixels_width = image_width;
1240 basepixels_height = image_height;
1241 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1243 if (textureflags & TEXF_ALPHA)
1245 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1246 if (basepixels[j] < 255)
1248 if (j < basepixels_width * basepixels_height * 4)
1250 // has transparent pixels
1251 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1252 for (j = 0;j < image_width * image_height * 4;j += 4)
1257 pixels[j+3] = basepixels[j+3];
1259 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1264 // _norm is the name used by tenebrae and has been adopted as standard
1267 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1269 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1273 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1275 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1276 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1277 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1279 Mem_Free(bumppixels);
1281 else if (r_shadow_bumpscale_basetexture.value > 0)
1283 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1284 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1285 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1289 // _luma is supported for tenebrae compatibility
1290 // (I think it's a very stupid name, but oh well)
1291 // _glow is the preferred name
1292 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;}
1293 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;}
1294 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;}
1295 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;}
1298 Mem_Free(basepixels);
1303 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)
1308 for (i = 0;i < width*height;i++)
1309 if (((unsigned char *)&palette[in[i]])[3] > 0)
1311 if (i == width*height)
1314 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1317 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)
1320 unsigned char *temp1, *temp2;
1321 skinframe_t *skinframe;
1323 if (cls.state == ca_dedicated)
1326 // if already loaded just return it, otherwise make a new skinframe
1327 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1328 if (skinframe && skinframe->base)
1331 skinframe->stain = NULL;
1332 skinframe->merged = NULL;
1333 skinframe->base = r_texture_notexture;
1334 skinframe->pants = NULL;
1335 skinframe->shirt = NULL;
1336 skinframe->nmap = r_texture_blanknormalmap;
1337 skinframe->gloss = NULL;
1338 skinframe->glow = NULL;
1339 skinframe->fog = NULL;
1341 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1345 if (bitsperpixel == 32)
1347 if (r_shadow_bumpscale_basetexture.value > 0)
1349 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1350 temp2 = temp1 + width * height * 4;
1351 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1352 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1355 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1356 if (textureflags & TEXF_ALPHA)
1358 for (i = 3;i < width * height * 4;i += 4)
1359 if (skindata[i] < 255)
1361 if (i < width * height * 4)
1363 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1364 memcpy(fogpixels, skindata, width * height * 4);
1365 for (i = 0;i < width * height * 4;i += 4)
1366 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1367 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1368 Mem_Free(fogpixels);
1372 else if (bitsperpixel == 8)
1374 if (r_shadow_bumpscale_basetexture.value > 0)
1376 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1377 temp2 = temp1 + width * height * 4;
1378 if (bitsperpixel == 32)
1379 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1382 // use either a custom palette or the quake palette
1383 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1384 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1386 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1389 // use either a custom palette, or the quake palette
1390 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
1391 if (!palette && loadglowtexture)
1392 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1393 if (!palette && loadpantsandshirt)
1395 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1396 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1398 if (skinframe->pants || skinframe->shirt)
1399 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1400 if (textureflags & TEXF_ALPHA)
1402 // if not using a custom alphapalette, use the quake one
1404 alphapalette = palette_alpha;
1405 for (i = 0;i < width * height;i++)
1406 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1408 if (i < width * height)
1409 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1416 skinframe_t *R_SkinFrame_LoadMissing(void)
1418 skinframe_t *skinframe;
1420 if (cls.state == ca_dedicated)
1423 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1424 skinframe->stain = NULL;
1425 skinframe->merged = NULL;
1426 skinframe->base = r_texture_notexture;
1427 skinframe->pants = NULL;
1428 skinframe->shirt = NULL;
1429 skinframe->nmap = r_texture_blanknormalmap;
1430 skinframe->gloss = NULL;
1431 skinframe->glow = NULL;
1432 skinframe->fog = NULL;
1437 void gl_main_start(void)
1442 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1443 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1445 alpha = 1 - exp(r / ((double)x*(double)x));
1446 if (x == FOGMASKTABLEWIDTH - 1)
1448 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1451 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1452 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1454 // set up r_skinframe loading system for textures
1455 memset(&r_skinframe, 0, sizeof(r_skinframe));
1456 r_skinframe.loadsequence = 1;
1457 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1459 r_main_texturepool = R_AllocTexturePool();
1460 R_BuildBlankTextures();
1462 if (gl_texturecubemap)
1465 R_BuildNormalizationCube();
1467 R_BuildFogTexture();
1468 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1469 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1470 memset(&r_svbsp, 0, sizeof (r_svbsp));
1473 void gl_main_shutdown(void)
1475 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1476 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1478 // clear out the r_skinframe state
1479 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1480 memset(&r_skinframe, 0, sizeof(r_skinframe));
1483 Mem_Free(r_svbsp.nodes);
1484 memset(&r_svbsp, 0, sizeof (r_svbsp));
1485 R_FreeTexturePool(&r_main_texturepool);
1486 r_texture_blanknormalmap = NULL;
1487 r_texture_white = NULL;
1488 r_texture_grey128 = NULL;
1489 r_texture_black = NULL;
1490 r_texture_whitecube = NULL;
1491 r_texture_normalizationcube = NULL;
1492 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1496 extern void CL_ParseEntityLump(char *entitystring);
1497 void gl_main_newmap(void)
1499 // FIXME: move this code to client
1501 char *entities, entname[MAX_QPATH];
1504 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1505 l = (int)strlen(entname) - 4;
1506 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1508 memcpy(entname + l, ".ent", 5);
1509 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1511 CL_ParseEntityLump(entities);
1516 if (cl.worldmodel->brush.entities)
1517 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1521 void GL_Main_Init(void)
1523 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1525 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1526 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1527 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1528 if (gamemode == GAME_NEHAHRA)
1530 Cvar_RegisterVariable (&gl_fogenable);
1531 Cvar_RegisterVariable (&gl_fogdensity);
1532 Cvar_RegisterVariable (&gl_fogred);
1533 Cvar_RegisterVariable (&gl_foggreen);
1534 Cvar_RegisterVariable (&gl_fogblue);
1535 Cvar_RegisterVariable (&gl_fogstart);
1536 Cvar_RegisterVariable (&gl_fogend);
1538 Cvar_RegisterVariable(&r_depthfirst);
1539 Cvar_RegisterVariable(&r_nearclip);
1540 Cvar_RegisterVariable(&r_showbboxes);
1541 Cvar_RegisterVariable(&r_showsurfaces);
1542 Cvar_RegisterVariable(&r_showtris);
1543 Cvar_RegisterVariable(&r_shownormals);
1544 Cvar_RegisterVariable(&r_showlighting);
1545 Cvar_RegisterVariable(&r_showshadowvolumes);
1546 Cvar_RegisterVariable(&r_showcollisionbrushes);
1547 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1548 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1549 Cvar_RegisterVariable(&r_showdisabledepthtest);
1550 Cvar_RegisterVariable(&r_drawportals);
1551 Cvar_RegisterVariable(&r_drawentities);
1552 Cvar_RegisterVariable(&r_cullentities_trace);
1553 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1554 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1555 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1556 Cvar_RegisterVariable(&r_drawviewmodel);
1557 Cvar_RegisterVariable(&r_speeds);
1558 Cvar_RegisterVariable(&r_fullbrights);
1559 Cvar_RegisterVariable(&r_wateralpha);
1560 Cvar_RegisterVariable(&r_dynamic);
1561 Cvar_RegisterVariable(&r_fullbright);
1562 Cvar_RegisterVariable(&r_shadows);
1563 Cvar_RegisterVariable(&r_shadows_throwdistance);
1564 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1565 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1566 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1567 Cvar_RegisterVariable(&r_textureunits);
1568 Cvar_RegisterVariable(&r_glsl);
1569 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1570 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1571 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1572 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1573 Cvar_RegisterVariable(&r_lerpsprites);
1574 Cvar_RegisterVariable(&r_lerpmodels);
1575 Cvar_RegisterVariable(&r_waterscroll);
1576 Cvar_RegisterVariable(&r_bloom);
1577 Cvar_RegisterVariable(&r_bloom_colorscale);
1578 Cvar_RegisterVariable(&r_bloom_brighten);
1579 Cvar_RegisterVariable(&r_bloom_blur);
1580 Cvar_RegisterVariable(&r_bloom_resolution);
1581 Cvar_RegisterVariable(&r_bloom_colorexponent);
1582 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1583 Cvar_RegisterVariable(&r_hdr);
1584 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1585 Cvar_RegisterVariable(&r_glsl_contrastboost);
1586 Cvar_RegisterVariable(&r_hdr_glowintensity);
1587 Cvar_RegisterVariable(&r_hdr_range);
1588 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1589 Cvar_RegisterVariable(&developer_texturelogging);
1590 Cvar_RegisterVariable(&gl_lightmaps);
1591 Cvar_RegisterVariable(&r_test);
1592 Cvar_RegisterVariable(&r_batchmode);
1593 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1594 Cvar_SetValue("r_fullbrights", 0);
1595 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1598 extern void R_Textures_Init(void);
1599 extern void GL_Draw_Init(void);
1600 extern void GL_Main_Init(void);
1601 extern void R_Shadow_Init(void);
1602 extern void R_Sky_Init(void);
1603 extern void GL_Surf_Init(void);
1604 extern void R_Light_Init(void);
1605 extern void R_Particles_Init(void);
1606 extern void R_Explosion_Init(void);
1607 extern void gl_backend_init(void);
1608 extern void Sbar_Init(void);
1609 extern void R_LightningBeams_Init(void);
1610 extern void Mod_RenderInit(void);
1612 void Render_Init(void)
1625 R_LightningBeams_Init();
1634 extern char *ENGINE_EXTENSIONS;
1637 VID_CheckExtensions();
1639 // LordHavoc: report supported extensions
1640 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1642 // clear to black (loading plaque will be seen over this)
1644 qglClearColor(0,0,0,1);CHECKGLERROR
1645 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1648 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1652 for (i = 0;i < 4;i++)
1654 p = r_view.frustum + i;
1659 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1663 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1667 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1671 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1675 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1679 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1683 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1687 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1695 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1699 for (i = 0;i < numplanes;i++)
1706 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1710 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1714 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1718 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1722 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1726 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1730 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1734 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1742 //==================================================================================
1744 static void R_UpdateEntityLighting(entity_render_t *ent)
1746 vec3_t tempdiffusenormal;
1748 // fetch the lighting from the worldmodel data
1749 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));
1750 VectorClear(ent->modellight_diffuse);
1751 VectorClear(tempdiffusenormal);
1752 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1755 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1756 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1759 VectorSet(ent->modellight_ambient, 1, 1, 1);
1761 // move the light direction into modelspace coordinates for lighting code
1762 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1763 if(VectorLength2(ent->modellight_lightdir) > 0)
1765 VectorNormalize(ent->modellight_lightdir);
1769 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1772 // scale ambient and directional light contributions according to rendering variables
1773 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1774 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1775 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1776 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1777 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1778 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1781 static void R_View_UpdateEntityVisible (void)
1784 entity_render_t *ent;
1786 if (!r_drawentities.integer)
1789 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1790 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1792 // worldmodel can check visibility
1793 for (i = 0;i < r_refdef.numentities;i++)
1795 ent = r_refdef.entities[i];
1796 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));
1798 if(r_cullentities_trace.integer)
1800 for (i = 0;i < r_refdef.numentities;i++)
1802 ent = r_refdef.entities[i];
1803 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1805 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1806 ent->last_trace_visibility = realtime;
1807 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1808 r_viewcache.entityvisible[i] = 0;
1815 // no worldmodel or it can't check visibility
1816 for (i = 0;i < r_refdef.numentities;i++)
1818 ent = r_refdef.entities[i];
1819 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1823 // update entity lighting (even on hidden entities for r_shadows)
1824 for (i = 0;i < r_refdef.numentities;i++)
1825 R_UpdateEntityLighting(r_refdef.entities[i]);
1828 // only used if skyrendermasked, and normally returns false
1829 int R_DrawBrushModelsSky (void)
1832 entity_render_t *ent;
1834 if (!r_drawentities.integer)
1838 for (i = 0;i < r_refdef.numentities;i++)
1840 if (!r_viewcache.entityvisible[i])
1842 ent = r_refdef.entities[i];
1843 if (!ent->model || !ent->model->DrawSky)
1845 ent->model->DrawSky(ent);
1851 void R_DrawNoModel(entity_render_t *ent);
1852 void R_DrawModels(void)
1855 entity_render_t *ent;
1857 if (!r_drawentities.integer)
1860 for (i = 0;i < r_refdef.numentities;i++)
1862 if (!r_viewcache.entityvisible[i])
1864 ent = r_refdef.entities[i];
1865 r_refdef.stats.entities++;
1866 if (ent->model && ent->model->Draw != NULL)
1867 ent->model->Draw(ent);
1873 void R_DrawModelsDepth(void)
1876 entity_render_t *ent;
1878 if (!r_drawentities.integer)
1881 for (i = 0;i < r_refdef.numentities;i++)
1883 if (!r_viewcache.entityvisible[i])
1885 ent = r_refdef.entities[i];
1886 r_refdef.stats.entities++;
1887 if (ent->model && ent->model->DrawDepth != NULL)
1888 ent->model->DrawDepth(ent);
1892 static void R_View_SetFrustum(void)
1894 double slopex, slopey;
1896 // break apart the view matrix into vectors for various purposes
1897 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1898 VectorNegate(r_view.left, r_view.right);
1901 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1902 r_view.frustum[0].normal[1] = 0 - 0;
1903 r_view.frustum[0].normal[2] = -1 - 0;
1904 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1905 r_view.frustum[1].normal[1] = 0 + 0;
1906 r_view.frustum[1].normal[2] = -1 + 0;
1907 r_view.frustum[2].normal[0] = 0 - 0;
1908 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1909 r_view.frustum[2].normal[2] = -1 - 0;
1910 r_view.frustum[3].normal[0] = 0 + 0;
1911 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1912 r_view.frustum[3].normal[2] = -1 + 0;
1916 zNear = r_refdef.nearclip;
1917 nudge = 1.0 - 1.0 / (1<<23);
1918 r_view.frustum[4].normal[0] = 0 - 0;
1919 r_view.frustum[4].normal[1] = 0 - 0;
1920 r_view.frustum[4].normal[2] = -1 - -nudge;
1921 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1922 r_view.frustum[5].normal[0] = 0 + 0;
1923 r_view.frustum[5].normal[1] = 0 + 0;
1924 r_view.frustum[5].normal[2] = -1 + -nudge;
1925 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1931 r_view.frustum[0].normal[0] = m[3] - m[0];
1932 r_view.frustum[0].normal[1] = m[7] - m[4];
1933 r_view.frustum[0].normal[2] = m[11] - m[8];
1934 r_view.frustum[0].dist = m[15] - m[12];
1936 r_view.frustum[1].normal[0] = m[3] + m[0];
1937 r_view.frustum[1].normal[1] = m[7] + m[4];
1938 r_view.frustum[1].normal[2] = m[11] + m[8];
1939 r_view.frustum[1].dist = m[15] + m[12];
1941 r_view.frustum[2].normal[0] = m[3] - m[1];
1942 r_view.frustum[2].normal[1] = m[7] - m[5];
1943 r_view.frustum[2].normal[2] = m[11] - m[9];
1944 r_view.frustum[2].dist = m[15] - m[13];
1946 r_view.frustum[3].normal[0] = m[3] + m[1];
1947 r_view.frustum[3].normal[1] = m[7] + m[5];
1948 r_view.frustum[3].normal[2] = m[11] + m[9];
1949 r_view.frustum[3].dist = m[15] + m[13];
1951 r_view.frustum[4].normal[0] = m[3] - m[2];
1952 r_view.frustum[4].normal[1] = m[7] - m[6];
1953 r_view.frustum[4].normal[2] = m[11] - m[10];
1954 r_view.frustum[4].dist = m[15] - m[14];
1956 r_view.frustum[5].normal[0] = m[3] + m[2];
1957 r_view.frustum[5].normal[1] = m[7] + m[6];
1958 r_view.frustum[5].normal[2] = m[11] + m[10];
1959 r_view.frustum[5].dist = m[15] + m[14];
1964 if (r_view.useperspective)
1966 slopex = 1.0 / r_view.frustum_x;
1967 slopey = 1.0 / r_view.frustum_y;
1968 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1969 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1970 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1971 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1972 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1974 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1975 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1976 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1977 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1978 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1980 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1981 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1982 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1983 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1984 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1988 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1989 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
1990 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1991 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
1992 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1993 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1994 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1995 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
1996 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
1997 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2000 PlaneClassify(&r_view.frustum[0]);
2001 PlaneClassify(&r_view.frustum[1]);
2002 PlaneClassify(&r_view.frustum[2]);
2003 PlaneClassify(&r_view.frustum[3]);
2004 PlaneClassify(&r_view.frustum[4]);
2006 // LordHavoc: note to all quake engine coders, Quake had a special case
2007 // for 90 degrees which assumed a square view (wrong), so I removed it,
2008 // Quake2 has it disabled as well.
2010 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2011 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2012 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2013 //PlaneClassify(&frustum[0]);
2015 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2016 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2017 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2018 //PlaneClassify(&frustum[1]);
2020 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2021 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2022 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2023 //PlaneClassify(&frustum[2]);
2025 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2026 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2027 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2028 //PlaneClassify(&frustum[3]);
2031 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2032 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2033 //PlaneClassify(&frustum[4]);
2036 void R_View_Update(void)
2038 R_View_SetFrustum();
2039 R_View_WorldVisibility();
2040 R_View_UpdateEntityVisible();
2043 void R_SetupView(const matrix4x4_t *matrix)
2045 if (!r_view.useperspective)
2046 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);
2047 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2048 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2050 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2052 GL_SetupView_Orientation_FromEntity(matrix);
2055 void R_ResetViewRendering2D(void)
2057 if (gl_support_fragment_shader)
2059 qglUseProgramObjectARB(0);CHECKGLERROR
2064 // GL is weird because it's bottom to top, r_view.y is top to bottom
2065 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2066 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2067 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2068 GL_Color(1, 1, 1, 1);
2069 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2070 GL_BlendFunc(GL_ONE, GL_ZERO);
2071 GL_AlphaTest(false);
2072 GL_ScissorTest(false);
2073 GL_DepthMask(false);
2074 GL_DepthRange(0, 1);
2075 GL_DepthTest(false);
2076 R_Mesh_Matrix(&identitymatrix);
2077 R_Mesh_ResetTextureState();
2078 GL_PolygonOffset(0, 0);
2079 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2080 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2081 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2082 qglStencilMask(~0);CHECKGLERROR
2083 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2084 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2085 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2088 void R_ResetViewRendering3D(void)
2090 if (gl_support_fragment_shader)
2092 qglUseProgramObjectARB(0);CHECKGLERROR
2097 // GL is weird because it's bottom to top, r_view.y is top to bottom
2098 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2099 R_SetupView(&r_view.matrix);
2100 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2101 GL_Color(1, 1, 1, 1);
2102 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2103 GL_BlendFunc(GL_ONE, GL_ZERO);
2104 GL_AlphaTest(false);
2105 GL_ScissorTest(true);
2107 GL_DepthRange(0, 1);
2109 R_Mesh_Matrix(&identitymatrix);
2110 R_Mesh_ResetTextureState();
2111 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2112 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2113 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2114 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2115 qglStencilMask(~0);CHECKGLERROR
2116 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2117 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2118 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2122 R_Bloom_SetupShader(
2124 "// written by Forest 'LordHavoc' Hale\n"
2126 "// common definitions between vertex shader and fragment shader:\n"
2128 "#ifdef __GLSL_CG_DATA_TYPES\n"
2129 "#define myhalf half\n"
2130 "#define myhvec2 hvec2\n"
2131 "#define myhvec3 hvec3\n"
2132 "#define myhvec4 hvec4\n"
2134 "#define myhalf float\n"
2135 "#define myhvec2 vec2\n"
2136 "#define myhvec3 vec3\n"
2137 "#define myhvec4 vec4\n"
2140 "varying vec2 ScreenTexCoord;\n"
2141 "varying vec2 BloomTexCoord;\n"
2146 "// vertex shader specific:\n"
2147 "#ifdef VERTEX_SHADER\n"
2151 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2152 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2153 " // transform vertex to camera space, using ftransform to match non-VS\n"
2155 " gl_Position = ftransform();\n"
2158 "#endif // VERTEX_SHADER\n"
2163 "// fragment shader specific:\n"
2164 "#ifdef FRAGMENT_SHADER\n"
2169 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2170 " for (x = -BLUR_X;x <= BLUR_X;x++)
2171 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2172 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2173 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2174 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2176 " gl_FragColor = vec4(color);\n"
2179 "#endif // FRAGMENT_SHADER\n"
2182 void R_RenderScene(void);
2184 void R_Bloom_StartFrame(void)
2186 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2188 // set bloomwidth and bloomheight to the bloom resolution that will be
2189 // used (often less than the screen resolution for faster rendering)
2190 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2191 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2192 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2194 // calculate desired texture sizes
2195 if (gl_support_arb_texture_non_power_of_two)
2197 screentexturewidth = r_view.width;
2198 screentextureheight = r_view.height;
2199 bloomtexturewidth = r_bloomstate.bloomwidth;
2200 bloomtextureheight = r_bloomstate.bloomheight;
2204 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2205 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2206 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2207 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2212 screentexturewidth = screentextureheight = 0;
2214 else if (r_bloom.integer)
2219 screentexturewidth = screentextureheight = 0;
2220 bloomtexturewidth = bloomtextureheight = 0;
2223 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)
2225 // can't use bloom if the parameters are too weird
2226 // can't use bloom if the card does not support the texture size
2227 if (r_bloomstate.texture_screen)
2228 R_FreeTexture(r_bloomstate.texture_screen);
2229 if (r_bloomstate.texture_bloom)
2230 R_FreeTexture(r_bloomstate.texture_bloom);
2231 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2235 r_bloomstate.enabled = true;
2236 r_bloomstate.hdr = r_hdr.integer != 0;
2238 // allocate textures as needed
2239 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2241 if (r_bloomstate.texture_screen)
2242 R_FreeTexture(r_bloomstate.texture_screen);
2243 r_bloomstate.texture_screen = NULL;
2244 r_bloomstate.screentexturewidth = screentexturewidth;
2245 r_bloomstate.screentextureheight = screentextureheight;
2246 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2247 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);
2249 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2251 if (r_bloomstate.texture_bloom)
2252 R_FreeTexture(r_bloomstate.texture_bloom);
2253 r_bloomstate.texture_bloom = NULL;
2254 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2255 r_bloomstate.bloomtextureheight = bloomtextureheight;
2256 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2257 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);
2260 // set up a texcoord array for the full resolution screen image
2261 // (we have to keep this around to copy back during final render)
2262 r_bloomstate.screentexcoord2f[0] = 0;
2263 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2264 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2265 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2266 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2267 r_bloomstate.screentexcoord2f[5] = 0;
2268 r_bloomstate.screentexcoord2f[6] = 0;
2269 r_bloomstate.screentexcoord2f[7] = 0;
2271 // set up a texcoord array for the reduced resolution bloom image
2272 // (which will be additive blended over the screen image)
2273 r_bloomstate.bloomtexcoord2f[0] = 0;
2274 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2275 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2276 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2277 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2278 r_bloomstate.bloomtexcoord2f[5] = 0;
2279 r_bloomstate.bloomtexcoord2f[6] = 0;
2280 r_bloomstate.bloomtexcoord2f[7] = 0;
2283 void R_Bloom_CopyScreenTexture(float colorscale)
2285 r_refdef.stats.bloom++;
2287 R_ResetViewRendering2D();
2288 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2289 R_Mesh_ColorPointer(NULL, 0, 0);
2290 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2291 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2293 // copy view into the screen texture
2294 GL_ActiveTexture(0);
2296 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
2297 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2299 // now scale it down to the bloom texture size
2301 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2302 GL_BlendFunc(GL_ONE, GL_ZERO);
2303 GL_Color(colorscale, colorscale, colorscale, 1);
2304 // TODO: optimize with multitexture or GLSL
2305 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2306 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2308 // we now have a bloom image in the framebuffer
2309 // copy it into the bloom image texture for later processing
2310 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2311 GL_ActiveTexture(0);
2313 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
2314 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2317 void R_Bloom_CopyHDRTexture(void)
2319 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2320 GL_ActiveTexture(0);
2322 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
2323 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2326 void R_Bloom_MakeTexture(void)
2329 float xoffset, yoffset, r, brighten;
2331 r_refdef.stats.bloom++;
2333 R_ResetViewRendering2D();
2334 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2335 R_Mesh_ColorPointer(NULL, 0, 0);
2337 // we have a bloom image in the framebuffer
2339 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2341 for (x = 1;x < r_bloom_colorexponent.value;)
2344 r = bound(0, r_bloom_colorexponent.value / x, 1);
2345 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2346 GL_Color(r, r, r, 1);
2347 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2348 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2349 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2350 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2352 // copy the vertically blurred bloom view to a texture
2353 GL_ActiveTexture(0);
2355 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
2356 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2359 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2360 brighten = r_bloom_brighten.value;
2362 brighten *= r_hdr_range.value;
2363 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2364 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2366 for (dir = 0;dir < 2;dir++)
2368 // blend on at multiple vertical offsets to achieve a vertical blur
2369 // TODO: do offset blends using GLSL
2370 GL_BlendFunc(GL_ONE, GL_ZERO);
2371 for (x = -range;x <= range;x++)
2373 if (!dir){xoffset = 0;yoffset = x;}
2374 else {xoffset = x;yoffset = 0;}
2375 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2376 yoffset /= (float)r_bloomstate.bloomtextureheight;
2377 // compute a texcoord array with the specified x and y offset
2378 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2379 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2380 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2381 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2382 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2383 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2384 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2385 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2386 // this r value looks like a 'dot' particle, fading sharply to
2387 // black at the edges
2388 // (probably not realistic but looks good enough)
2389 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2390 //r = (dir ? 1.0f : brighten)/(range*2+1);
2391 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2392 GL_Color(r, r, r, 1);
2393 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2394 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2395 GL_BlendFunc(GL_ONE, GL_ONE);
2398 // copy the vertically blurred bloom view to a texture
2399 GL_ActiveTexture(0);
2401 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
2402 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2405 // apply subtract last
2406 // (just like it would be in a GLSL shader)
2407 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2409 GL_BlendFunc(GL_ONE, GL_ZERO);
2410 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2411 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2412 GL_Color(1, 1, 1, 1);
2413 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2414 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2416 GL_BlendFunc(GL_ONE, GL_ONE);
2417 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2418 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2419 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2420 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2421 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2422 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2423 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2425 // copy the darkened bloom view to a texture
2426 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2427 GL_ActiveTexture(0);
2429 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
2430 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2434 void R_HDR_RenderBloomTexture(void)
2436 int oldwidth, oldheight;
2438 oldwidth = r_view.width;
2439 oldheight = r_view.height;
2440 r_view.width = r_bloomstate.bloomwidth;
2441 r_view.height = r_bloomstate.bloomheight;
2443 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2444 // TODO: add exposure compensation features
2445 // TODO: add fp16 framebuffer support
2447 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2449 r_view.colorscale /= r_hdr_range.value;
2452 R_ResetViewRendering2D();
2454 R_Bloom_CopyHDRTexture();
2455 R_Bloom_MakeTexture();
2457 R_ResetViewRendering3D();
2460 if (r_timereport_active)
2461 R_TimeReport("clear");
2464 // restore the view settings
2465 r_view.width = oldwidth;
2466 r_view.height = oldheight;
2469 static void R_BlendView(void)
2471 if (r_bloomstate.enabled && r_bloomstate.hdr)
2473 // render high dynamic range bloom effect
2474 // the bloom texture was made earlier this render, so we just need to
2475 // blend it onto the screen...
2476 R_ResetViewRendering2D();
2477 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2478 R_Mesh_ColorPointer(NULL, 0, 0);
2479 GL_Color(1, 1, 1, 1);
2480 GL_BlendFunc(GL_ONE, GL_ONE);
2481 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2482 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2483 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2484 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2486 else if (r_bloomstate.enabled)
2488 // render simple bloom effect
2489 // copy the screen and shrink it and darken it for the bloom process
2490 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2491 // make the bloom texture
2492 R_Bloom_MakeTexture();
2493 // put the original screen image back in place and blend the bloom
2495 R_ResetViewRendering2D();
2496 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2497 R_Mesh_ColorPointer(NULL, 0, 0);
2498 GL_Color(1, 1, 1, 1);
2499 GL_BlendFunc(GL_ONE, GL_ZERO);
2500 // do both in one pass if possible
2501 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2502 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2503 if (r_textureunits.integer >= 2 && gl_combine.integer)
2505 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2506 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2507 R_Mesh_TexCoordPointer(1, 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;
2513 // now blend on the bloom texture
2514 GL_BlendFunc(GL_ONE, GL_ONE);
2515 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2516 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2518 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2519 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2521 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2523 // apply a color tint to the whole view
2524 R_ResetViewRendering2D();
2525 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2526 R_Mesh_ColorPointer(NULL, 0, 0);
2527 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2528 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2529 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2533 void R_RenderScene(void);
2535 matrix4x4_t r_waterscrollmatrix;
2537 void R_UpdateVariables(void)
2541 r_refdef.farclip = 4096;
2542 if (r_refdef.worldmodel)
2543 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2544 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2546 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2547 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2548 r_refdef.polygonfactor = 0;
2549 r_refdef.polygonoffset = 0;
2550 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2551 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2553 r_refdef.rtworld = r_shadow_realtime_world.integer;
2554 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2555 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2556 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2557 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2558 if (r_showsurfaces.integer)
2560 r_refdef.rtworld = false;
2561 r_refdef.rtworldshadows = false;
2562 r_refdef.rtdlight = false;
2563 r_refdef.rtdlightshadows = false;
2564 r_refdef.lightmapintensity = 0;
2567 if (gamemode == GAME_NEHAHRA)
2569 if (gl_fogenable.integer)
2571 r_refdef.oldgl_fogenable = true;
2572 r_refdef.fog_density = gl_fogdensity.value;
2573 r_refdef.fog_red = gl_fogred.value;
2574 r_refdef.fog_green = gl_foggreen.value;
2575 r_refdef.fog_blue = gl_fogblue.value;
2577 else if (r_refdef.oldgl_fogenable)
2579 r_refdef.oldgl_fogenable = false;
2580 r_refdef.fog_density = 0;
2581 r_refdef.fog_red = 0;
2582 r_refdef.fog_green = 0;
2583 r_refdef.fog_blue = 0;
2586 if (r_refdef.fog_density)
2588 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2589 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2590 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2592 if (r_refdef.fog_density)
2594 r_refdef.fogenabled = true;
2595 // this is the point where the fog reaches 0.9986 alpha, which we
2596 // consider a good enough cutoff point for the texture
2597 // (0.9986 * 256 == 255.6)
2598 r_refdef.fogrange = 400 / r_refdef.fog_density;
2599 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2600 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2601 // fog color was already set
2604 r_refdef.fogenabled = false;
2612 void R_RenderView(void)
2614 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2615 return; //Host_Error ("R_RenderView: NULL worldmodel");
2617 R_Shadow_UpdateWorldLightSelection();
2620 if (r_timereport_active)
2621 R_TimeReport("setup");
2624 if (r_timereport_active)
2625 R_TimeReport("visibility");
2627 R_ResetViewRendering3D();
2630 if (r_timereport_active)
2631 R_TimeReport("clear");
2633 R_Bloom_StartFrame();
2635 // this produces a bloom texture to be used in R_BlendView() later
2637 R_HDR_RenderBloomTexture();
2639 r_view.colorscale = r_hdr_scenebrightness.value;
2643 if (r_timereport_active)
2644 R_TimeReport("blendview");
2646 GL_Scissor(0, 0, vid.width, vid.height);
2647 GL_ScissorTest(false);
2651 extern void R_DrawLightningBeams (void);
2652 extern void VM_CL_AddPolygonsToMeshQueue (void);
2653 extern void R_DrawPortals (void);
2654 extern cvar_t cl_locs_show;
2655 static void R_DrawLocs(void);
2656 static void R_DrawEntityBBoxes(void);
2657 void R_RenderScene(void)
2659 // don't let sound skip if going slow
2660 if (r_refdef.extraupdate)
2663 R_ResetViewRendering3D();
2665 R_MeshQueue_BeginScene();
2669 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);
2671 if (cl.csqc_vidvars.drawworld)
2673 // don't let sound skip if going slow
2674 if (r_refdef.extraupdate)
2677 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2679 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2680 if (r_timereport_active)
2681 R_TimeReport("worldsky");
2684 if (R_DrawBrushModelsSky() && r_timereport_active)
2685 R_TimeReport("bmodelsky");
2688 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2690 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2691 if (r_timereport_active)
2692 R_TimeReport("worlddepth");
2694 if (r_depthfirst.integer >= 2)
2696 R_DrawModelsDepth();
2697 if (r_timereport_active)
2698 R_TimeReport("modeldepth");
2701 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2703 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2704 if (r_timereport_active)
2705 R_TimeReport("world");
2708 // don't let sound skip if going slow
2709 if (r_refdef.extraupdate)
2713 if (r_timereport_active)
2714 R_TimeReport("models");
2716 // don't let sound skip if going slow
2717 if (r_refdef.extraupdate)
2720 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2722 R_DrawModelShadows();
2724 R_ResetViewRendering3D();
2726 // don't let sound skip if going slow
2727 if (r_refdef.extraupdate)
2731 R_ShadowVolumeLighting(false);
2732 if (r_timereport_active)
2733 R_TimeReport("rtlights");
2735 // don't let sound skip if going slow
2736 if (r_refdef.extraupdate)
2739 if (cl.csqc_vidvars.drawworld)
2741 R_DrawLightningBeams();
2742 if (r_timereport_active)
2743 R_TimeReport("lightning");
2746 if (r_timereport_active)
2747 R_TimeReport("particles");
2750 if (r_timereport_active)
2751 R_TimeReport("explosions");
2754 if (gl_support_fragment_shader)
2756 qglUseProgramObjectARB(0);CHECKGLERROR
2758 VM_CL_AddPolygonsToMeshQueue();
2760 if (cl_locs_show.integer)
2763 if (r_timereport_active)
2764 R_TimeReport("showlocs");
2767 if (r_drawportals.integer)
2770 if (r_timereport_active)
2771 R_TimeReport("portals");
2774 if (r_showbboxes.value > 0)
2776 R_DrawEntityBBoxes();
2777 if (r_timereport_active)
2778 R_TimeReport("bboxes");
2781 if (gl_support_fragment_shader)
2783 qglUseProgramObjectARB(0);CHECKGLERROR
2785 R_MeshQueue_RenderTransparent();
2786 if (r_timereport_active)
2787 R_TimeReport("drawtrans");
2789 if (gl_support_fragment_shader)
2791 qglUseProgramObjectARB(0);CHECKGLERROR
2794 if (cl.csqc_vidvars.drawworld)
2797 if (r_timereport_active)
2798 R_TimeReport("coronas");
2801 // don't let sound skip if going slow
2802 if (r_refdef.extraupdate)
2805 R_ResetViewRendering2D();
2808 static const int bboxelements[36] =
2818 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2821 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2822 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2823 GL_DepthMask(false);
2824 GL_DepthRange(0, 1);
2825 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2826 R_Mesh_Matrix(&identitymatrix);
2827 R_Mesh_ResetTextureState();
2829 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2830 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2831 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2832 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2833 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2834 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2835 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2836 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2837 R_FillColors(color4f, 8, cr, cg, cb, ca);
2838 if (r_refdef.fogenabled)
2840 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2842 f1 = FogPoint_World(v);
2844 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2845 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2846 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2849 R_Mesh_VertexPointer(vertex3f, 0, 0);
2850 R_Mesh_ColorPointer(color4f, 0, 0);
2851 R_Mesh_ResetTextureState();
2852 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2855 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2859 prvm_edict_t *edict;
2860 // this function draws bounding boxes of server entities
2864 for (i = 0;i < numsurfaces;i++)
2866 edict = PRVM_EDICT_NUM(surfacelist[i]);
2867 switch ((int)edict->fields.server->solid)
2869 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2870 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2871 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2872 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2873 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2874 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2876 color[3] *= r_showbboxes.value;
2877 color[3] = bound(0, color[3], 1);
2878 GL_DepthTest(!r_showdisabledepthtest.integer);
2879 GL_CullFace(GL_BACK);
2880 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2885 static void R_DrawEntityBBoxes(void)
2888 prvm_edict_t *edict;
2890 // this function draws bounding boxes of server entities
2894 for (i = 0;i < prog->num_edicts;i++)
2896 edict = PRVM_EDICT_NUM(i);
2897 if (edict->priv.server->free)
2899 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2900 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2905 int nomodelelements[24] =
2917 float nomodelvertex3f[6*3] =
2927 float nomodelcolor4f[6*4] =
2929 0.0f, 0.0f, 0.5f, 1.0f,
2930 0.0f, 0.0f, 0.5f, 1.0f,
2931 0.0f, 0.5f, 0.0f, 1.0f,
2932 0.0f, 0.5f, 0.0f, 1.0f,
2933 0.5f, 0.0f, 0.0f, 1.0f,
2934 0.5f, 0.0f, 0.0f, 1.0f
2937 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2942 // this is only called once per entity so numsurfaces is always 1, and
2943 // surfacelist is always {0}, so this code does not handle batches
2944 R_Mesh_Matrix(&ent->matrix);
2946 if (ent->flags & EF_ADDITIVE)
2948 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2949 GL_DepthMask(false);
2951 else if (ent->alpha < 1)
2953 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2954 GL_DepthMask(false);
2958 GL_BlendFunc(GL_ONE, GL_ZERO);
2961 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2962 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2963 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2964 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2965 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2966 if (r_refdef.fogenabled)
2969 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2970 R_Mesh_ColorPointer(color4f, 0, 0);
2971 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2972 f1 = FogPoint_World(org);
2974 for (i = 0, c = color4f;i < 6;i++, c += 4)
2976 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2977 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2978 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2982 else if (ent->alpha != 1)
2984 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2985 R_Mesh_ColorPointer(color4f, 0, 0);
2986 for (i = 0, c = color4f;i < 6;i++, c += 4)
2990 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2991 R_Mesh_ResetTextureState();
2992 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2995 void R_DrawNoModel(entity_render_t *ent)
2998 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2999 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3000 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3002 // R_DrawNoModelCallback(ent, 0);
3005 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3007 vec3_t right1, right2, diff, normal;
3009 VectorSubtract (org2, org1, normal);
3011 // calculate 'right' vector for start
3012 VectorSubtract (r_view.origin, org1, diff);
3013 CrossProduct (normal, diff, right1);
3014 VectorNormalize (right1);
3016 // calculate 'right' vector for end
3017 VectorSubtract (r_view.origin, org2, diff);
3018 CrossProduct (normal, diff, right2);
3019 VectorNormalize (right2);
3021 vert[ 0] = org1[0] + width * right1[0];
3022 vert[ 1] = org1[1] + width * right1[1];
3023 vert[ 2] = org1[2] + width * right1[2];
3024 vert[ 3] = org1[0] - width * right1[0];
3025 vert[ 4] = org1[1] - width * right1[1];
3026 vert[ 5] = org1[2] - width * right1[2];
3027 vert[ 6] = org2[0] - width * right2[0];
3028 vert[ 7] = org2[1] - width * right2[1];
3029 vert[ 8] = org2[2] - width * right2[2];
3030 vert[ 9] = org2[0] + width * right2[0];
3031 vert[10] = org2[1] + width * right2[1];
3032 vert[11] = org2[2] + width * right2[2];
3035 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3037 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)
3042 if (r_refdef.fogenabled)
3043 fog = FogPoint_World(origin);
3045 R_Mesh_Matrix(&identitymatrix);
3046 GL_BlendFunc(blendfunc1, blendfunc2);
3052 GL_CullFace(GL_BACK);
3055 GL_CullFace(GL_FRONT);
3057 GL_DepthMask(false);
3058 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3059 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3060 GL_DepthTest(!depthdisable);
3062 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3063 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3064 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3065 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3066 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3067 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3068 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3069 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3070 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3071 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3072 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3073 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3075 R_Mesh_VertexPointer(vertex3f, 0, 0);
3076 R_Mesh_ColorPointer(NULL, 0, 0);
3077 R_Mesh_ResetTextureState();
3078 R_Mesh_TexBind(0, R_GetTexture(texture));
3079 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3080 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3081 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3082 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3084 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3086 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3087 GL_BlendFunc(blendfunc1, GL_ONE);
3089 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);
3090 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3094 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3099 VectorSet(v, x, y, z);
3100 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3101 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3103 if (i == mesh->numvertices)
3105 if (mesh->numvertices < mesh->maxvertices)
3107 VectorCopy(v, vertex3f);
3108 mesh->numvertices++;
3110 return mesh->numvertices;
3116 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3120 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3121 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3122 e = mesh->element3i + mesh->numtriangles * 3;
3123 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3125 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3126 if (mesh->numtriangles < mesh->maxtriangles)
3131 mesh->numtriangles++;
3133 element[1] = element[2];
3137 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3141 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3142 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3143 e = mesh->element3i + mesh->numtriangles * 3;
3144 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3146 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3147 if (mesh->numtriangles < mesh->maxtriangles)
3152 mesh->numtriangles++;
3154 element[1] = element[2];
3158 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3159 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3161 int planenum, planenum2;
3164 mplane_t *plane, *plane2;
3166 double temppoints[2][256*3];
3167 // figure out how large a bounding box we need to properly compute this brush
3169 for (w = 0;w < numplanes;w++)
3170 maxdist = max(maxdist, planes[w].dist);
3171 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3172 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3173 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3177 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3178 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3180 if (planenum2 == planenum)
3182 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);
3185 if (tempnumpoints < 3)
3187 // generate elements forming a triangle fan for this polygon
3188 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3192 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3195 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3196 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3197 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);
3198 GL_LockArrays(0, brush->numpoints);
3199 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3200 GL_LockArrays(0, 0);
3203 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3206 if (!surface->num_collisiontriangles)
3208 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3209 i = (int)(((size_t)surface) / sizeof(msurface_t));
3210 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);
3211 GL_LockArrays(0, surface->num_collisionvertices);
3212 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3213 GL_LockArrays(0, 0);
3216 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)
3218 texturelayer_t *layer;
3219 layer = t->currentlayers + t->currentnumlayers++;
3221 layer->depthmask = depthmask;
3222 layer->blendfunc1 = blendfunc1;
3223 layer->blendfunc2 = blendfunc2;
3224 layer->texture = texture;
3225 layer->texmatrix = *matrix;
3226 layer->color[0] = r * r_view.colorscale;
3227 layer->color[1] = g * r_view.colorscale;
3228 layer->color[2] = b * r_view.colorscale;
3229 layer->color[3] = a;
3232 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3235 index = parms[2] + r_refdef.time * parms[3];
3236 index -= floor(index);
3240 case Q3WAVEFUNC_NONE:
3241 case Q3WAVEFUNC_NOISE:
3242 case Q3WAVEFUNC_COUNT:
3245 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3246 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3247 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3248 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3249 case Q3WAVEFUNC_TRIANGLE:
3251 f = index - floor(index);
3262 return (float)(parms[0] + parms[1] * f);
3265 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3268 model_t *model = ent->model;
3271 q3shaderinfo_layer_tcmod_t *tcmod;
3273 // switch to an alternate material if this is a q1bsp animated material
3275 texture_t *texture = t;
3276 int s = ent->skinnum;
3277 if ((unsigned int)s >= (unsigned int)model->numskins)
3279 if (model->skinscenes)
3281 if (model->skinscenes[s].framecount > 1)
3282 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3284 s = model->skinscenes[s].firstframe;
3287 t = t + s * model->num_surfaces;
3290 // use an alternate animation if the entity's frame is not 0,
3291 // and only if the texture has an alternate animation
3292 if (ent->frame2 != 0 && t->anim_total[1])
3293 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3295 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3297 texture->currentframe = t;
3300 // update currentskinframe to be a qw skin or animation frame
3301 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3303 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3305 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3306 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3307 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);
3309 t->currentskinframe = r_qwskincache_skinframe[i];
3310 if (t->currentskinframe == NULL)
3311 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3313 else if (t->numskinframes >= 2)
3314 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3315 if (t->backgroundnumskinframes >= 2)
3316 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3318 t->currentmaterialflags = t->basematerialflags;
3319 t->currentalpha = ent->alpha;
3320 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3321 t->currentalpha *= r_wateralpha.value;
3322 if (!(ent->flags & RENDER_LIGHT))
3323 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3324 if (ent->effects & EF_ADDITIVE)
3325 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3326 else if (t->currentalpha < 1)
3327 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3328 if (ent->effects & EF_DOUBLESIDED)
3329 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3330 if (ent->effects & EF_NODEPTHTEST)
3331 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3332 if (ent->flags & RENDER_VIEWMODEL)
3333 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3334 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3335 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3337 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3340 switch(tcmod->tcmod)
3344 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3345 matrix = r_waterscrollmatrix;
3347 matrix = identitymatrix;
3349 case Q3TCMOD_ENTITYTRANSLATE:
3350 // this is used in Q3 to allow the gamecode to control texcoord
3351 // scrolling on the entity, which is not supported in darkplaces yet.
3352 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3354 case Q3TCMOD_ROTATE:
3355 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3356 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3357 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3360 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3362 case Q3TCMOD_SCROLL:
3363 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3365 case Q3TCMOD_STRETCH:
3366 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3367 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3369 case Q3TCMOD_TRANSFORM:
3370 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3371 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3372 VectorSet(tcmat + 6, 0 , 0 , 1);
3373 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3374 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3376 case Q3TCMOD_TURBULENT:
3377 // this is handled in the RSurf_PrepareVertices function
3378 matrix = identitymatrix;
3381 // either replace or concatenate the transformation
3383 t->currenttexmatrix = matrix;
3386 matrix4x4_t temp = t->currenttexmatrix;
3387 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3391 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3392 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3393 t->glosstexture = r_texture_white;
3394 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3395 t->backgroundglosstexture = r_texture_white;
3396 t->specularpower = r_shadow_glossexponent.value;
3397 // TODO: store reference values for these in the texture?
3398 t->specularscale = 0;
3399 if (r_shadow_gloss.integer > 0)
3401 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3403 if (r_shadow_glossintensity.value > 0)
3405 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3406 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3407 t->specularscale = r_shadow_glossintensity.value;
3410 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3411 t->specularscale = r_shadow_gloss2intensity.value;
3414 // lightmaps mode looks bad with dlights using actual texturing, so turn
3415 // off the colormap and glossmap, but leave the normalmap on as it still
3416 // accurately represents the shading involved
3417 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3419 t->basetexture = r_texture_white;
3420 t->specularscale = 0;
3423 t->currentpolygonfactor = r_refdef.polygonfactor;
3424 t->currentpolygonoffset = r_refdef.polygonoffset;
3425 // submodels are biased to avoid z-fighting with world surfaces that they
3426 // may be exactly overlapping (avoids z-fighting artifacts on certain
3427 // doors and things in Quake maps)
3428 if (ent->model->brush.submodel)
3430 t->currentpolygonfactor = r_refdef.polygonfactor + r_polygonoffset_submodel_factor.value;
3431 t->currentpolygonoffset = r_refdef.polygonoffset + r_polygonoffset_submodel_offset.value;
3434 VectorClear(t->dlightcolor);
3435 t->currentnumlayers = 0;
3436 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3438 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3440 int blendfunc1, blendfunc2, depthmask;
3441 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3443 blendfunc1 = GL_SRC_ALPHA;
3444 blendfunc2 = GL_ONE;
3446 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3448 blendfunc1 = GL_SRC_ALPHA;
3449 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3451 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3453 blendfunc1 = t->customblendfunc[0];
3454 blendfunc2 = t->customblendfunc[1];
3458 blendfunc1 = GL_ONE;
3459 blendfunc2 = GL_ZERO;
3461 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3462 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3464 rtexture_t *currentbasetexture;
3466 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3467 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3468 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3469 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3471 // fullbright is not affected by r_refdef.lightmapintensity
3472 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3473 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3474 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);
3475 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3476 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);
3481 // set the color tint used for lights affecting this surface
3482 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3484 // q3bsp has no lightmap updates, so the lightstylevalue that
3485 // would normally be baked into the lightmap must be
3486 // applied to the color
3487 if (ent->model->type == mod_brushq3)
3488 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3489 colorscale *= r_refdef.lightmapintensity;
3490 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);
3491 if (r_ambient.value >= (1.0f/64.0f))
3492 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);
3493 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3495 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);
3496 if (r_ambient.value >= (1.0f/64.0f))
3497 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);
3499 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3501 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);
3502 if (r_ambient.value >= (1.0f/64.0f))
3503 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);
3506 if (t->currentskinframe->glow != NULL)
3507 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);
3508 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3510 // if this is opaque use alpha blend which will darken the earlier
3513 // if this is an alpha blended material, all the earlier passes
3514 // were darkened by fog already, so we only need to add the fog
3515 // color ontop through the fog mask texture
3517 // if this is an additive blended material, all the earlier passes
3518 // were darkened by fog already, and we should not add fog color
3519 // (because the background was not darkened, there is no fog color
3520 // that was lost behind it).
3521 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);
3528 void R_UpdateAllTextureInfo(entity_render_t *ent)
3532 for (i = 0;i < ent->model->num_texturesperskin;i++)
3533 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3536 rsurfacestate_t rsurface;
3538 void R_Mesh_ResizeArrays(int newvertices)
3541 if (rsurface.array_size >= newvertices)
3543 if (rsurface.array_modelvertex3f)
3544 Mem_Free(rsurface.array_modelvertex3f);
3545 rsurface.array_size = (newvertices + 1023) & ~1023;
3546 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3547 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3548 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3549 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3550 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3551 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3552 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3553 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3554 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3555 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3556 rsurface.array_color4f = base + rsurface.array_size * 27;
3557 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3560 void RSurf_CleanUp(void)
3563 if (rsurface.mode == RSURFMODE_GLSL)
3565 qglUseProgramObjectARB(0);CHECKGLERROR
3567 GL_AlphaTest(false);
3568 rsurface.mode = RSURFMODE_NONE;
3569 rsurface.uselightmaptexture = false;
3570 rsurface.texture = NULL;
3573 void RSurf_ActiveWorldEntity(void)
3575 model_t *model = r_refdef.worldmodel;
3577 if (rsurface.array_size < model->surfmesh.num_vertices)
3578 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3579 rsurface.matrix = identitymatrix;
3580 rsurface.inversematrix = identitymatrix;
3581 R_Mesh_Matrix(&identitymatrix);
3582 VectorCopy(r_view.origin, rsurface.modelorg);
3583 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3584 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3585 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3586 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3587 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3588 rsurface.frameblend[0].frame = 0;
3589 rsurface.frameblend[0].lerp = 1;
3590 rsurface.frameblend[1].frame = 0;
3591 rsurface.frameblend[1].lerp = 0;
3592 rsurface.frameblend[2].frame = 0;
3593 rsurface.frameblend[2].lerp = 0;
3594 rsurface.frameblend[3].frame = 0;
3595 rsurface.frameblend[3].lerp = 0;
3596 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3597 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3598 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3599 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3600 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3601 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3602 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3603 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3604 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3605 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3606 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3607 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3608 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3609 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3610 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3611 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3612 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3613 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3614 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3615 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3616 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3617 rsurface.modelelement3i = model->surfmesh.data_element3i;
3618 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3619 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3620 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3621 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3622 rsurface.modelsurfaces = model->data_surfaces;
3623 rsurface.generatedvertex = false;
3624 rsurface.vertex3f = rsurface.modelvertex3f;
3625 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3626 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3627 rsurface.svector3f = rsurface.modelsvector3f;
3628 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3629 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3630 rsurface.tvector3f = rsurface.modeltvector3f;
3631 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3632 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3633 rsurface.normal3f = rsurface.modelnormal3f;
3634 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3635 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3636 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3639 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3641 model_t *model = ent->model;
3643 if (rsurface.array_size < model->surfmesh.num_vertices)
3644 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3645 rsurface.matrix = ent->matrix;
3646 rsurface.inversematrix = ent->inversematrix;
3647 R_Mesh_Matrix(&rsurface.matrix);
3648 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3649 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3650 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3651 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3652 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3653 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3654 rsurface.frameblend[0] = ent->frameblend[0];
3655 rsurface.frameblend[1] = ent->frameblend[1];
3656 rsurface.frameblend[2] = ent->frameblend[2];
3657 rsurface.frameblend[3] = ent->frameblend[3];
3658 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3662 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3663 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3664 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3665 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3666 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3668 else if (wantnormals)
3670 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3671 rsurface.modelsvector3f = NULL;
3672 rsurface.modeltvector3f = NULL;
3673 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3674 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3678 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3679 rsurface.modelsvector3f = NULL;
3680 rsurface.modeltvector3f = NULL;
3681 rsurface.modelnormal3f = NULL;
3682 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3684 rsurface.modelvertex3f_bufferobject = 0;
3685 rsurface.modelvertex3f_bufferoffset = 0;
3686 rsurface.modelsvector3f_bufferobject = 0;
3687 rsurface.modelsvector3f_bufferoffset = 0;
3688 rsurface.modeltvector3f_bufferobject = 0;
3689 rsurface.modeltvector3f_bufferoffset = 0;
3690 rsurface.modelnormal3f_bufferobject = 0;
3691 rsurface.modelnormal3f_bufferoffset = 0;
3692 rsurface.generatedvertex = true;
3696 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3697 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3698 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3699 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3700 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3701 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3702 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3703 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3704 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3705 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3706 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3707 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3708 rsurface.generatedvertex = false;
3710 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3711 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3712 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3713 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3714 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3715 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3716 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3717 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3718 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3719 rsurface.modelelement3i = model->surfmesh.data_element3i;
3720 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3721 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3722 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3723 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3724 rsurface.modelsurfaces = model->data_surfaces;
3725 rsurface.vertex3f = rsurface.modelvertex3f;
3726 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3727 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3728 rsurface.svector3f = rsurface.modelsvector3f;
3729 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3730 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3731 rsurface.tvector3f = rsurface.modeltvector3f;
3732 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3733 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3734 rsurface.normal3f = rsurface.modelnormal3f;
3735 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3736 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3737 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3740 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3741 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3744 int texturesurfaceindex;
3749 const float *v1, *in_tc;
3751 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3753 q3shaderinfo_deform_t *deform;
3754 // 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
3755 if (rsurface.generatedvertex)
3757 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3758 generatenormals = true;
3759 for (i = 0;i < Q3MAXDEFORMS;i++)
3761 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3763 generatetangents = true;
3764 generatenormals = true;
3766 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3767 generatenormals = true;
3769 if (generatenormals && !rsurface.modelnormal3f)
3771 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3772 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3773 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3774 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3776 if (generatetangents && !rsurface.modelsvector3f)
3778 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3779 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3780 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3781 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3782 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3783 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3784 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);
3787 rsurface.vertex3f = rsurface.modelvertex3f;
3788 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3789 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3790 rsurface.svector3f = rsurface.modelsvector3f;
3791 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3792 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3793 rsurface.tvector3f = rsurface.modeltvector3f;
3794 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3795 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3796 rsurface.normal3f = rsurface.modelnormal3f;
3797 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3798 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3799 // if vertices are deformed (sprite flares and things in maps, possibly
3800 // water waves, bulges and other deformations), generate them into
3801 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3802 // (may be static model data or generated data for an animated model, or
3803 // the previous deform pass)
3804 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3806 switch (deform->deform)
3809 case Q3DEFORM_PROJECTIONSHADOW:
3810 case Q3DEFORM_TEXT0:
3811 case Q3DEFORM_TEXT1:
3812 case Q3DEFORM_TEXT2:
3813 case Q3DEFORM_TEXT3:
3814 case Q3DEFORM_TEXT4:
3815 case Q3DEFORM_TEXT5:
3816 case Q3DEFORM_TEXT6:
3817 case Q3DEFORM_TEXT7:
3820 case Q3DEFORM_AUTOSPRITE:
3821 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3822 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3823 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3824 VectorNormalize(newforward);
3825 VectorNormalize(newright);
3826 VectorNormalize(newup);
3827 // make deformed versions of only the model vertices used by the specified surfaces
3828 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3830 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3831 // a single autosprite surface can contain multiple sprites...
3832 for (j = 0;j < surface->num_vertices - 3;j += 4)
3834 VectorClear(center);
3835 for (i = 0;i < 4;i++)
3836 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3837 VectorScale(center, 0.25f, center);
3838 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3839 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3840 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3841 for (i = 0;i < 4;i++)
3843 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3844 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3847 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);
3848 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);
3850 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3851 rsurface.vertex3f_bufferobject = 0;
3852 rsurface.vertex3f_bufferoffset = 0;
3853 rsurface.svector3f = rsurface.array_deformedsvector3f;
3854 rsurface.svector3f_bufferobject = 0;
3855 rsurface.svector3f_bufferoffset = 0;
3856 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3857 rsurface.tvector3f_bufferobject = 0;
3858 rsurface.tvector3f_bufferoffset = 0;
3859 rsurface.normal3f = rsurface.array_deformednormal3f;
3860 rsurface.normal3f_bufferobject = 0;
3861 rsurface.normal3f_bufferoffset = 0;
3863 case Q3DEFORM_AUTOSPRITE2:
3864 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3867 VectorNormalize(newforward);
3868 VectorNormalize(newright);
3869 VectorNormalize(newup);
3870 // make deformed versions of only the model vertices used by the specified surfaces
3871 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3873 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3874 const float *v1, *v2;
3884 memset(shortest, 0, sizeof(shortest));
3885 // a single autosprite surface can contain multiple sprites...
3886 for (j = 0;j < surface->num_vertices - 3;j += 4)
3888 VectorClear(center);
3889 for (i = 0;i < 4;i++)
3890 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3891 VectorScale(center, 0.25f, center);
3892 // find the two shortest edges, then use them to define the
3893 // axis vectors for rotating around the central axis
3894 for (i = 0;i < 6;i++)
3896 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3897 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3899 Debug_PolygonBegin(NULL, 0, false, 0);
3900 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
3901 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);
3902 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
3905 l = VectorDistance2(v1, v2);
3906 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
3908 l += (1.0f / 1024.0f);
3909 if (shortest[0].length2 > l || i == 0)
3911 shortest[1] = shortest[0];
3912 shortest[0].length2 = l;
3913 shortest[0].v1 = v1;
3914 shortest[0].v2 = v2;
3916 else if (shortest[1].length2 > l || i == 1)
3918 shortest[1].length2 = l;
3919 shortest[1].v1 = v1;
3920 shortest[1].v2 = v2;
3923 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
3924 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
3926 Debug_PolygonBegin(NULL, 0, false, 0);
3927 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
3928 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);
3929 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
3932 // this calculates the right vector from the shortest edge
3933 // and the up vector from the edge midpoints
3934 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
3935 VectorNormalize(right);
3936 VectorSubtract(end, start, up);
3937 VectorNormalize(up);
3938 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3939 //VectorSubtract(rsurface.modelorg, center, forward);
3940 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
3941 VectorNegate(forward, forward);
3942 VectorReflect(forward, 0, up, forward);
3943 VectorNormalize(forward);
3944 CrossProduct(up, forward, newright);
3945 VectorNormalize(newright);
3947 Debug_PolygonBegin(NULL, 0, false, 0);
3948 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);
3949 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[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);
3954 Debug_PolygonBegin(NULL, 0, false, 0);
3955 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
3956 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
3957 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3960 // rotate the quad around the up axis vector, this is made
3961 // especially easy by the fact we know the quad is flat,
3962 // so we only have to subtract the center position and
3963 // measure distance along the right vector, and then
3964 // multiply that by the newright vector and add back the
3966 // we also need to subtract the old position to undo the
3967 // displacement from the center, which we do with a
3968 // DotProduct, the subtraction/addition of center is also
3969 // optimized into DotProducts here
3970 l = DotProduct(right, center);
3971 for (i = 0;i < 4;i++)
3973 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3974 f = DotProduct(right, v1) - l;
3975 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3978 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);
3979 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);
3981 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3982 rsurface.vertex3f_bufferobject = 0;
3983 rsurface.vertex3f_bufferoffset = 0;
3984 rsurface.svector3f = rsurface.array_deformedsvector3f;
3985 rsurface.svector3f_bufferobject = 0;
3986 rsurface.svector3f_bufferoffset = 0;
3987 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3988 rsurface.tvector3f_bufferobject = 0;
3989 rsurface.tvector3f_bufferoffset = 0;
3990 rsurface.normal3f = rsurface.array_deformednormal3f;
3991 rsurface.normal3f_bufferobject = 0;
3992 rsurface.normal3f_bufferoffset = 0;
3994 case Q3DEFORM_NORMAL:
3995 // deform the normals to make reflections wavey
3996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3999 for (j = 0;j < surface->num_vertices;j++)
4002 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4003 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4004 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4005 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4006 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4007 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4008 VectorNormalize(normal);
4010 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);
4012 rsurface.svector3f = rsurface.array_deformedsvector3f;
4013 rsurface.svector3f_bufferobject = 0;
4014 rsurface.svector3f_bufferoffset = 0;
4015 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4016 rsurface.tvector3f_bufferobject = 0;
4017 rsurface.tvector3f_bufferoffset = 0;
4018 rsurface.normal3f = rsurface.array_deformednormal3f;
4019 rsurface.normal3f_bufferobject = 0;
4020 rsurface.normal3f_bufferoffset = 0;
4023 // deform vertex array to make wavey water and flags and such
4024 waveparms[0] = deform->waveparms[0];
4025 waveparms[1] = deform->waveparms[1];
4026 waveparms[2] = deform->waveparms[2];
4027 waveparms[3] = deform->waveparms[3];
4028 // this is how a divisor of vertex influence on deformation
4029 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4030 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4031 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4033 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4034 for (j = 0;j < surface->num_vertices;j++)
4036 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4037 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4038 // if the wavefunc depends on time, evaluate it per-vertex
4041 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4042 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4044 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4047 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4048 rsurface.vertex3f_bufferobject = 0;
4049 rsurface.vertex3f_bufferoffset = 0;
4051 case Q3DEFORM_BULGE:
4052 // deform vertex array to make the surface have moving bulges
4053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4055 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4056 for (j = 0;j < surface->num_vertices;j++)
4058 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4059 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4062 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4063 rsurface.vertex3f_bufferobject = 0;
4064 rsurface.vertex3f_bufferoffset = 0;
4067 // deform vertex array
4068 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4069 VectorScale(deform->parms, scale, waveparms);
4070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4072 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4073 for (j = 0;j < surface->num_vertices;j++)
4074 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4076 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4077 rsurface.vertex3f_bufferobject = 0;
4078 rsurface.vertex3f_bufferoffset = 0;
4082 // generate texcoords based on the chosen texcoord source
4083 switch(rsurface.texture->tcgen.tcgen)
4086 case Q3TCGEN_TEXTURE:
4087 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4088 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4089 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4091 case Q3TCGEN_LIGHTMAP:
4092 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4093 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4094 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4096 case Q3TCGEN_VECTOR:
4097 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4100 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)
4102 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4103 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4106 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4107 rsurface.texcoordtexture2f_bufferobject = 0;
4108 rsurface.texcoordtexture2f_bufferoffset = 0;
4110 case Q3TCGEN_ENVIRONMENT:
4111 // make environment reflections using a spheremap
4112 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4114 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4115 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4116 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4117 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4118 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4120 float l, d, eyedir[3];
4121 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4122 l = 0.5f / VectorLength(eyedir);
4123 d = DotProduct(normal, eyedir)*2;
4124 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4125 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4128 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4129 rsurface.texcoordtexture2f_bufferobject = 0;
4130 rsurface.texcoordtexture2f_bufferoffset = 0;
4133 // the only tcmod that needs software vertex processing is turbulent, so
4134 // check for it here and apply the changes if needed
4135 // and we only support that as the first one
4136 // (handling a mixture of turbulent and other tcmods would be problematic
4137 // without punting it entirely to a software path)
4138 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4140 amplitude = rsurface.texture->tcmods[0].parms[1];
4141 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4142 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4144 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4145 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)
4147 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4148 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4151 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4152 rsurface.texcoordtexture2f_bufferobject = 0;
4153 rsurface.texcoordtexture2f_bufferoffset = 0;
4155 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4156 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4157 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4158 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4161 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4164 const msurface_t *surface = texturesurfacelist[0];
4165 const msurface_t *surface2;
4170 // TODO: lock all array ranges before render, rather than on each surface
4171 if (texturenumsurfaces == 1)
4173 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4174 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));
4176 else if (r_batchmode.integer == 2)
4178 #define MAXBATCHTRIANGLES 4096
4179 int batchtriangles = 0;
4180 int batchelements[MAXBATCHTRIANGLES*3];
4181 for (i = 0;i < texturenumsurfaces;i = j)
4183 surface = texturesurfacelist[i];
4185 if (surface->num_triangles > MAXBATCHTRIANGLES)
4187 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));
4190 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4191 batchtriangles = surface->num_triangles;
4192 firstvertex = surface->num_firstvertex;
4193 endvertex = surface->num_firstvertex + surface->num_vertices;
4194 for (;j < texturenumsurfaces;j++)
4196 surface2 = texturesurfacelist[j];
4197 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4199 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4200 batchtriangles += surface2->num_triangles;
4201 firstvertex = min(firstvertex, surface2->num_firstvertex);
4202 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4204 surface2 = texturesurfacelist[j-1];
4205 numvertices = endvertex - firstvertex;
4206 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4209 else if (r_batchmode.integer == 1)
4211 for (i = 0;i < texturenumsurfaces;i = j)
4213 surface = texturesurfacelist[i];
4214 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4215 if (texturesurfacelist[j] != surface2)
4217 surface2 = texturesurfacelist[j-1];
4218 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4219 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4220 GL_LockArrays(surface->num_firstvertex, numvertices);
4221 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4226 for (i = 0;i < texturenumsurfaces;i++)
4228 surface = texturesurfacelist[i];
4229 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4230 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));
4235 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4239 const msurface_t *surface = texturesurfacelist[0];
4240 const msurface_t *surface2;
4245 // TODO: lock all array ranges before render, rather than on each surface
4246 if (texturenumsurfaces == 1)
4248 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4249 if (deluxemaptexunit >= 0)
4250 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4251 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4252 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));
4254 else if (r_batchmode.integer == 2)
4256 #define MAXBATCHTRIANGLES 4096
4257 int batchtriangles = 0;
4258 int batchelements[MAXBATCHTRIANGLES*3];
4259 for (i = 0;i < texturenumsurfaces;i = j)
4261 surface = texturesurfacelist[i];
4262 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4263 if (deluxemaptexunit >= 0)
4264 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4266 if (surface->num_triangles > MAXBATCHTRIANGLES)
4268 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));
4271 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4272 batchtriangles = surface->num_triangles;
4273 firstvertex = surface->num_firstvertex;
4274 endvertex = surface->num_firstvertex + surface->num_vertices;
4275 for (;j < texturenumsurfaces;j++)
4277 surface2 = texturesurfacelist[j];
4278 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4280 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4281 batchtriangles += surface2->num_triangles;
4282 firstvertex = min(firstvertex, surface2->num_firstvertex);
4283 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4285 surface2 = texturesurfacelist[j-1];
4286 numvertices = endvertex - firstvertex;
4287 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4290 else if (r_batchmode.integer == 1)
4293 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4294 for (i = 0;i < texturenumsurfaces;i = j)
4296 surface = texturesurfacelist[i];
4297 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4298 if (texturesurfacelist[j] != surface2)
4300 Con_Printf(" %i", j - i);
4303 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4305 for (i = 0;i < texturenumsurfaces;i = j)
4307 surface = texturesurfacelist[i];
4308 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4309 if (deluxemaptexunit >= 0)
4310 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4311 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4312 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4315 Con_Printf(" %i", j - i);
4317 surface2 = texturesurfacelist[j-1];
4318 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4319 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4320 GL_LockArrays(surface->num_firstvertex, numvertices);
4321 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4329 for (i = 0;i < texturenumsurfaces;i++)
4331 surface = texturesurfacelist[i];
4332 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4333 if (deluxemaptexunit >= 0)
4334 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4335 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4336 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));
4341 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4344 int texturesurfaceindex;
4345 if (r_showsurfaces.integer == 2)
4347 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4349 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4350 for (j = 0;j < surface->num_triangles;j++)
4352 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4353 GL_Color(f, f, f, 1);
4354 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)));
4360 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4362 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4363 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4364 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);
4365 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4366 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));
4371 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4373 int texturesurfaceindex;
4377 if (rsurface.lightmapcolor4f)
4379 // generate color arrays for the surfaces in this list
4380 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4382 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4383 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)
4385 f = FogPoint_Model(v);
4395 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4397 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4398 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)
4400 f = FogPoint_Model(v);
4408 rsurface.lightmapcolor4f = rsurface.array_color4f;
4409 rsurface.lightmapcolor4f_bufferobject = 0;
4410 rsurface.lightmapcolor4f_bufferoffset = 0;
4413 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4415 int texturesurfaceindex;
4418 if (!rsurface.lightmapcolor4f)
4420 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4422 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4423 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)
4431 rsurface.lightmapcolor4f = rsurface.array_color4f;
4432 rsurface.lightmapcolor4f_bufferobject = 0;
4433 rsurface.lightmapcolor4f_bufferoffset = 0;
4436 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4439 rsurface.lightmapcolor4f = NULL;
4440 rsurface.lightmapcolor4f_bufferobject = 0;
4441 rsurface.lightmapcolor4f_bufferoffset = 0;
4442 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4443 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4444 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4445 GL_Color(r, g, b, a);
4446 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4449 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4451 // TODO: optimize applyfog && applycolor case
4452 // just apply fog if necessary, and tint the fog color array if necessary
4453 rsurface.lightmapcolor4f = NULL;
4454 rsurface.lightmapcolor4f_bufferobject = 0;
4455 rsurface.lightmapcolor4f_bufferoffset = 0;
4456 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4457 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4458 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4459 GL_Color(r, g, b, a);
4460 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4463 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4465 int texturesurfaceindex;
4469 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4471 // generate color arrays for the surfaces in this list
4472 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4474 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4475 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4477 if (surface->lightmapinfo->samples)
4479 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4480 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4481 VectorScale(lm, scale, c);
4482 if (surface->lightmapinfo->styles[1] != 255)
4484 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4486 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4487 VectorMA(c, scale, lm, c);
4488 if (surface->lightmapinfo->styles[2] != 255)
4491 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4492 VectorMA(c, scale, lm, c);
4493 if (surface->lightmapinfo->styles[3] != 255)
4496 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4497 VectorMA(c, scale, lm, c);
4507 rsurface.lightmapcolor4f = rsurface.array_color4f;
4508 rsurface.lightmapcolor4f_bufferobject = 0;
4509 rsurface.lightmapcolor4f_bufferoffset = 0;
4513 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4514 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4515 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4517 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4518 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4519 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4520 GL_Color(r, g, b, a);
4521 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4524 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4526 int texturesurfaceindex;
4530 vec3_t ambientcolor;
4531 vec3_t diffusecolor;
4535 VectorCopy(rsurface.modellight_lightdir, lightdir);
4536 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4537 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4538 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4539 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4540 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4541 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4542 if (VectorLength2(diffusecolor) > 0)
4544 // generate color arrays for the surfaces in this list
4545 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4547 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4548 int numverts = surface->num_vertices;
4549 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4550 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4551 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4552 // q3-style directional shading
4553 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4555 if ((f = DotProduct(c2, lightdir)) > 0)
4556 VectorMA(ambientcolor, f, diffusecolor, c);
4558 VectorCopy(ambientcolor, c);
4567 rsurface.lightmapcolor4f = rsurface.array_color4f;
4568 rsurface.lightmapcolor4f_bufferobject = 0;
4569 rsurface.lightmapcolor4f_bufferoffset = 0;
4573 r = ambientcolor[0];
4574 g = ambientcolor[1];
4575 b = ambientcolor[2];
4576 rsurface.lightmapcolor4f = NULL;
4577 rsurface.lightmapcolor4f_bufferobject = 0;
4578 rsurface.lightmapcolor4f_bufferoffset = 0;
4580 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4581 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4582 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4583 GL_Color(r, g, b, a);
4584 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4587 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4589 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4590 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4591 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4592 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4593 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4595 rsurface.mode = RSURFMODE_SHOWSURFACES;
4597 GL_BlendFunc(GL_ONE, GL_ZERO);
4598 R_Mesh_ColorPointer(NULL, 0, 0);
4599 R_Mesh_ResetTextureState();
4601 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4602 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4605 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4607 // transparent sky would be ridiculous
4608 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4610 if (rsurface.mode != RSURFMODE_SKY)
4612 if (rsurface.mode == RSURFMODE_GLSL)
4614 qglUseProgramObjectARB(0);CHECKGLERROR
4616 rsurface.mode = RSURFMODE_SKY;
4620 skyrendernow = false;
4622 // restore entity matrix
4623 R_Mesh_Matrix(&rsurface.matrix);
4625 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4626 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4627 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4628 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4630 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4631 // skymasking on them, and Quake3 never did sky masking (unlike
4632 // software Quake and software Quake2), so disable the sky masking
4633 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4634 // and skymasking also looks very bad when noclipping outside the
4635 // level, so don't use it then either.
4636 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4638 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4639 R_Mesh_ColorPointer(NULL, 0, 0);
4640 R_Mesh_ResetTextureState();
4641 if (skyrendermasked)
4643 // depth-only (masking)
4644 GL_ColorMask(0,0,0,0);
4645 // just to make sure that braindead drivers don't draw
4646 // anything despite that colormask...
4647 GL_BlendFunc(GL_ZERO, GL_ONE);
4652 GL_BlendFunc(GL_ONE, GL_ZERO);
4654 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4655 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4656 if (skyrendermasked)
4657 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4661 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4663 if (rsurface.mode != RSURFMODE_GLSL)
4665 rsurface.mode = RSURFMODE_GLSL;
4666 R_Mesh_ResetTextureState();
4669 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4670 if (!r_glsl_permutation)
4673 if (rsurface.lightmode == 2)
4674 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4676 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4677 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4678 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4679 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4680 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4681 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4683 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]);
4684 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4686 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
4687 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4688 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4689 R_Mesh_ColorPointer(NULL, 0, 0);
4691 else if (rsurface.uselightmaptexture)
4693 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4694 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4695 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4696 R_Mesh_ColorPointer(NULL, 0, 0);
4700 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4701 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4702 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4703 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4706 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4707 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4709 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4710 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4715 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4717 // OpenGL 1.3 path - anything not completely ancient
4718 int texturesurfaceindex;
4719 qboolean applycolor;
4723 const texturelayer_t *layer;
4724 if (rsurface.mode != RSURFMODE_MULTIPASS)
4725 rsurface.mode = RSURFMODE_MULTIPASS;
4726 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4727 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4730 int layertexrgbscale;
4731 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4733 if (layerindex == 0)
4737 GL_AlphaTest(false);
4738 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4741 GL_DepthMask(layer->depthmask);
4742 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4743 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4745 layertexrgbscale = 4;
4746 VectorScale(layer->color, 0.25f, layercolor);
4748 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4750 layertexrgbscale = 2;
4751 VectorScale(layer->color, 0.5f, layercolor);
4755 layertexrgbscale = 1;
4756 VectorScale(layer->color, 1.0f, layercolor);
4758 layercolor[3] = layer->color[3];
4759 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4760 R_Mesh_ColorPointer(NULL, 0, 0);
4761 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4762 switch (layer->type)
4764 case TEXTURELAYERTYPE_LITTEXTURE:
4765 memset(&m, 0, sizeof(m));
4766 m.tex[0] = R_GetTexture(r_texture_white);
4767 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4768 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4769 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4770 m.tex[1] = R_GetTexture(layer->texture);
4771 m.texmatrix[1] = layer->texmatrix;
4772 m.texrgbscale[1] = layertexrgbscale;
4773 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4774 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4775 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4776 R_Mesh_TextureState(&m);
4777 if (rsurface.lightmode == 2)
4778 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4779 else if (rsurface.uselightmaptexture)
4780 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4782 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4784 case TEXTURELAYERTYPE_TEXTURE:
4785 memset(&m, 0, sizeof(m));
4786 m.tex[0] = R_GetTexture(layer->texture);
4787 m.texmatrix[0] = layer->texmatrix;
4788 m.texrgbscale[0] = layertexrgbscale;
4789 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4790 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4791 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4792 R_Mesh_TextureState(&m);
4793 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4795 case TEXTURELAYERTYPE_FOG:
4796 memset(&m, 0, sizeof(m));
4797 m.texrgbscale[0] = layertexrgbscale;
4800 m.tex[0] = R_GetTexture(layer->texture);
4801 m.texmatrix[0] = layer->texmatrix;
4802 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4803 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4804 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4806 R_Mesh_TextureState(&m);
4807 // generate a color array for the fog pass
4808 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4813 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4814 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)
4816 f = 1 - FogPoint_Model(v);
4817 c[0] = layercolor[0];
4818 c[1] = layercolor[1];
4819 c[2] = layercolor[2];
4820 c[3] = f * layercolor[3];
4823 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4826 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4828 GL_LockArrays(0, 0);
4831 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4833 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4834 GL_AlphaTest(false);
4838 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4840 // OpenGL 1.1 - crusty old voodoo path
4841 int texturesurfaceindex;
4845 const texturelayer_t *layer;
4846 if (rsurface.mode != RSURFMODE_MULTIPASS)
4847 rsurface.mode = RSURFMODE_MULTIPASS;
4848 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4849 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4851 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4853 if (layerindex == 0)
4857 GL_AlphaTest(false);
4858 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4861 GL_DepthMask(layer->depthmask);
4862 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4863 R_Mesh_ColorPointer(NULL, 0, 0);
4864 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4865 switch (layer->type)
4867 case TEXTURELAYERTYPE_LITTEXTURE:
4868 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4870 // two-pass lit texture with 2x rgbscale
4871 // first the lightmap pass
4872 memset(&m, 0, sizeof(m));
4873 m.tex[0] = R_GetTexture(r_texture_white);
4874 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4875 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4876 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4877 R_Mesh_TextureState(&m);
4878 if (rsurface.lightmode == 2)
4879 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4880 else if (rsurface.uselightmaptexture)
4881 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4883 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4884 GL_LockArrays(0, 0);
4885 // then apply the texture to it
4886 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4887 memset(&m, 0, sizeof(m));
4888 m.tex[0] = R_GetTexture(layer->texture);
4889 m.texmatrix[0] = layer->texmatrix;
4890 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4891 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4892 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4893 R_Mesh_TextureState(&m);
4894 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);
4898 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4899 memset(&m, 0, sizeof(m));
4900 m.tex[0] = R_GetTexture(layer->texture);
4901 m.texmatrix[0] = layer->texmatrix;
4902 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4903 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4904 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4905 R_Mesh_TextureState(&m);
4906 if (rsurface.lightmode == 2)
4907 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);
4909 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);
4912 case TEXTURELAYERTYPE_TEXTURE:
4913 // singletexture unlit texture with transparency support
4914 memset(&m, 0, sizeof(m));
4915 m.tex[0] = R_GetTexture(layer->texture);
4916 m.texmatrix[0] = layer->texmatrix;
4917 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4918 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4919 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4920 R_Mesh_TextureState(&m);
4921 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);
4923 case TEXTURELAYERTYPE_FOG:
4924 // singletexture fogging
4925 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4928 memset(&m, 0, sizeof(m));
4929 m.tex[0] = R_GetTexture(layer->texture);
4930 m.texmatrix[0] = layer->texmatrix;
4931 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4932 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4933 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4934 R_Mesh_TextureState(&m);
4937 R_Mesh_ResetTextureState();
4938 // generate a color array for the fog pass
4939 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4943 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4944 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)
4946 f = 1 - FogPoint_Model(v);
4947 c[0] = layer->color[0];
4948 c[1] = layer->color[1];
4949 c[2] = layer->color[2];
4950 c[3] = f * layer->color[3];
4953 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4956 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4958 GL_LockArrays(0, 0);
4961 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4963 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4964 GL_AlphaTest(false);
4968 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4970 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4972 rsurface.rtlight = NULL;
4976 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4978 if (rsurface.mode != RSURFMODE_MULTIPASS)
4979 rsurface.mode = RSURFMODE_MULTIPASS;
4980 if (r_depthfirst.integer == 3)
4982 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4983 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
4987 GL_ColorMask(0,0,0,0);
4990 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4991 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4992 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4994 GL_BlendFunc(GL_ONE, GL_ZERO);
4996 GL_AlphaTest(false);
4997 R_Mesh_ColorPointer(NULL, 0, 0);
4998 R_Mesh_ResetTextureState();
4999 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5000 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5001 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5002 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5004 else if (r_depthfirst.integer == 3)
5006 else if (r_showsurfaces.integer)
5008 if (rsurface.mode != RSURFMODE_MULTIPASS)
5009 rsurface.mode = RSURFMODE_MULTIPASS;
5010 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5011 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5013 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5014 GL_BlendFunc(GL_ONE, GL_ZERO);
5015 GL_DepthMask(writedepth);
5017 GL_AlphaTest(false);
5018 R_Mesh_ColorPointer(NULL, 0, 0);
5019 R_Mesh_ResetTextureState();
5020 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5021 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5022 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5024 else if (gl_lightmaps.integer)
5027 if (rsurface.mode != RSURFMODE_MULTIPASS)
5028 rsurface.mode = RSURFMODE_MULTIPASS;
5029 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5031 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5032 GL_BlendFunc(GL_ONE, GL_ZERO);
5033 GL_DepthMask(writedepth);
5035 GL_AlphaTest(false);
5036 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5037 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5038 R_Mesh_ColorPointer(NULL, 0, 0);
5039 memset(&m, 0, sizeof(m));
5040 m.tex[0] = R_GetTexture(r_texture_white);
5041 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5042 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5043 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5044 R_Mesh_TextureState(&m);
5045 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5046 if (rsurface.lightmode == 2)
5047 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5048 else if (rsurface.uselightmaptexture)
5049 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5051 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5052 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5054 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5056 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5057 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5059 else if (rsurface.texture->currentnumlayers)
5061 // write depth for anything we skipped on the depth-only pass earlier
5062 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5064 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5065 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5066 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5067 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5068 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5069 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5070 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5071 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5072 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5073 if (r_glsl.integer && gl_support_fragment_shader)
5074 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5075 else if (gl_combine.integer && r_textureunits.integer >= 2)
5076 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5078 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5079 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5082 GL_LockArrays(0, 0);
5085 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5088 int texturenumsurfaces, endsurface;
5090 msurface_t *surface;
5091 msurface_t *texturesurfacelist[1024];
5093 // if the model is static it doesn't matter what value we give for
5094 // wantnormals and wanttangents, so this logic uses only rules applicable
5095 // to a model, knowing that they are meaningless otherwise
5096 if (ent == r_refdef.worldentity)
5097 RSurf_ActiveWorldEntity();
5098 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5099 RSurf_ActiveModelEntity(ent, false, false);
5101 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5103 for (i = 0;i < numsurfaces;i = j)
5106 surface = rsurface.modelsurfaces + surfacelist[i];
5107 texture = surface->texture;
5108 R_UpdateTextureInfo(ent, texture);
5109 rsurface.texture = texture->currentframe;
5110 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5111 // scan ahead until we find a different texture
5112 endsurface = min(i + 1024, numsurfaces);
5113 texturenumsurfaces = 0;
5114 texturesurfacelist[texturenumsurfaces++] = surface;
5115 for (;j < endsurface;j++)
5117 surface = rsurface.modelsurfaces + surfacelist[j];
5118 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5120 texturesurfacelist[texturenumsurfaces++] = surface;
5122 // render the range of surfaces
5123 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5129 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5132 vec3_t tempcenter, center;
5134 // break the surface list down into batches by texture and use of lightmapping
5135 for (i = 0;i < numsurfaces;i = j)
5138 // texture is the base texture pointer, rsurface.texture is the
5139 // current frame/skin the texture is directing us to use (for example
5140 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5141 // use skin 1 instead)
5142 texture = surfacelist[i]->texture;
5143 rsurface.texture = texture->currentframe;
5144 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5145 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5147 // if this texture is not the kind we want, skip ahead to the next one
5148 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5152 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5154 // transparent surfaces get pushed off into the transparent queue
5155 const msurface_t *surface = surfacelist[i];
5158 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5159 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5160 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5161 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5162 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5166 // simply scan ahead until we find a different texture or lightmap state
5167 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5169 // render the range of surfaces
5170 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5175 float locboxvertex3f[6*4*3] =
5177 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5178 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5179 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5180 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5181 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5182 1,0,0, 0,0,0, 0,1,0, 1,1,0
5185 int locboxelement3i[6*2*3] =
5195 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5198 cl_locnode_t *loc = (cl_locnode_t *)ent;
5200 float vertex3f[6*4*3];
5202 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5203 GL_DepthMask(false);
5204 GL_DepthRange(0, 1);
5205 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5207 GL_CullFace(GL_NONE);
5208 R_Mesh_Matrix(&identitymatrix);
5210 R_Mesh_VertexPointer(vertex3f, 0, 0);
5211 R_Mesh_ColorPointer(NULL, 0, 0);
5212 R_Mesh_ResetTextureState();
5215 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5216 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5217 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5218 surfacelist[0] < 0 ? 0.5f : 0.125f);
5220 if (VectorCompare(loc->mins, loc->maxs))
5222 VectorSet(size, 2, 2, 2);
5223 VectorMA(loc->mins, -0.5f, size, mins);
5227 VectorCopy(loc->mins, mins);
5228 VectorSubtract(loc->maxs, loc->mins, size);
5231 for (i = 0;i < 6*4*3;)
5232 for (j = 0;j < 3;j++, i++)
5233 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5235 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5238 void R_DrawLocs(void)
5241 cl_locnode_t *loc, *nearestloc;
5243 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5244 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5246 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5247 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5251 void R_DrawCollisionBrushes(entity_render_t *ent)
5255 msurface_t *surface;
5256 model_t *model = ent->model;
5257 if (!model->brush.num_brushes)
5260 R_Mesh_ColorPointer(NULL, 0, 0);
5261 R_Mesh_ResetTextureState();
5262 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5263 GL_DepthMask(false);
5264 GL_DepthRange(0, 1);
5265 GL_DepthTest(!r_showdisabledepthtest.integer);
5266 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5267 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5268 if (brush->colbrushf && brush->colbrushf->numtriangles)
5269 R_DrawCollisionBrush(brush->colbrushf);
5270 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5271 if (surface->num_collisiontriangles)
5272 R_DrawCollisionSurface(ent, surface);
5273 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5276 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5279 const int *elements;
5280 msurface_t *surface;
5281 model_t *model = ent->model;
5284 GL_DepthRange(0, 1);
5285 GL_DepthTest(!r_showdisabledepthtest.integer);
5286 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5288 GL_BlendFunc(GL_ONE, GL_ZERO);
5289 R_Mesh_ColorPointer(NULL, 0, 0);
5290 R_Mesh_ResetTextureState();
5291 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5293 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5295 rsurface.texture = surface->texture->currentframe;
5296 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5298 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5301 if (!rsurface.texture->currentlayers->depthmask)
5302 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5303 else if (ent == r_refdef.worldentity)
5304 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5306 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5307 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5310 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5312 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5313 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5314 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5315 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5322 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5324 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5326 VectorCopy(rsurface.vertex3f + l * 3, v);
5327 qglVertex3f(v[0], v[1], v[2]);
5328 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5329 qglVertex3f(v[0], v[1], v[2]);
5333 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5335 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5337 VectorCopy(rsurface.vertex3f + l * 3, v);
5338 qglVertex3f(v[0], v[1], v[2]);
5339 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5340 qglVertex3f(v[0], v[1], v[2]);
5344 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5346 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5348 VectorCopy(rsurface.vertex3f + l * 3, v);
5349 qglVertex3f(v[0], v[1], v[2]);
5350 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5351 qglVertex3f(v[0], v[1], v[2]);
5358 rsurface.texture = NULL;
5361 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5362 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5364 int i, j, endj, f, flagsmask;
5365 int counttriangles = 0;
5366 msurface_t *surface, **surfacechain;
5368 model_t *model = r_refdef.worldmodel;
5369 const int maxsurfacelist = 1024;
5370 int numsurfacelist = 0;
5371 msurface_t *surfacelist[1024];
5375 RSurf_ActiveWorldEntity();
5377 // update light styles
5378 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5380 for (i = 0;i < model->brushq1.light_styles;i++)
5382 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5384 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5385 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5386 for (;(surface = *surfacechain);surfacechain++)
5387 surface->cached_dlight = true;
5392 R_UpdateAllTextureInfo(r_refdef.worldentity);
5393 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5396 rsurface.uselightmaptexture = false;
5397 rsurface.texture = NULL;
5399 j = model->firstmodelsurface;
5400 endj = j + model->nummodelsurfaces;
5403 // quickly skip over non-visible surfaces
5404 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5406 // quickly iterate over visible surfaces
5407 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5409 // process this surface
5410 surface = model->data_surfaces + j;
5411 // if this surface fits the criteria, add it to the list
5412 if (surface->num_triangles)
5414 // if lightmap parameters changed, rebuild lightmap texture
5415 if (surface->cached_dlight)
5416 R_BuildLightMap(r_refdef.worldentity, surface);
5417 // add face to draw list
5418 surfacelist[numsurfacelist++] = surface;
5419 counttriangles += surface->num_triangles;
5420 if (numsurfacelist >= maxsurfacelist)
5422 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5429 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5430 r_refdef.stats.entities_triangles += counttriangles;
5433 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5434 R_DrawCollisionBrushes(r_refdef.worldentity);
5436 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5437 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5440 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5442 int i, f, flagsmask;
5443 int counttriangles = 0;
5444 msurface_t *surface, *endsurface, **surfacechain;
5446 model_t *model = ent->model;
5447 const int maxsurfacelist = 1024;
5448 int numsurfacelist = 0;
5449 msurface_t *surfacelist[1024];
5453 // if the model is static it doesn't matter what value we give for
5454 // wantnormals and wanttangents, so this logic uses only rules applicable
5455 // to a model, knowing that they are meaningless otherwise
5456 if (ent == r_refdef.worldentity)
5457 RSurf_ActiveWorldEntity();
5458 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5459 RSurf_ActiveModelEntity(ent, false, false);
5461 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5463 // update light styles
5464 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5466 for (i = 0;i < model->brushq1.light_styles;i++)
5468 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5470 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5471 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5472 for (;(surface = *surfacechain);surfacechain++)
5473 surface->cached_dlight = true;
5478 R_UpdateAllTextureInfo(ent);
5479 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5482 rsurface.uselightmaptexture = false;
5483 rsurface.texture = NULL;
5485 surface = model->data_surfaces + model->firstmodelsurface;
5486 endsurface = surface + model->nummodelsurfaces;
5487 for (;surface < endsurface;surface++)
5489 // if this surface fits the criteria, add it to the list
5490 if (surface->num_triangles)
5492 // if lightmap parameters changed, rebuild lightmap texture
5493 if (surface->cached_dlight)
5494 R_BuildLightMap(ent, surface);
5495 // add face to draw list
5496 surfacelist[numsurfacelist++] = surface;
5497 counttriangles += surface->num_triangles;
5498 if (numsurfacelist >= maxsurfacelist)
5500 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5506 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5507 r_refdef.stats.entities_triangles += counttriangles;
5510 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5511 R_DrawCollisionBrushes(ent);
5513 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5514 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);