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)
987 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
988 Cvar_SetValueQuick(&r_glsl, 0);
989 return 0; // no bit left to clear
991 // reduce i more quickly whenever it would not remove any bits
992 if (!(permutation & i))
995 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
996 R_GLSL_CompilePermutation(shaderfilename, permutation);
997 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1002 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1004 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1005 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1006 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1008 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1009 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1010 if (permutation & SHADERPERMUTATION_DIFFUSE)
1012 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1013 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1014 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1015 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1019 // ambient only is simpler
1020 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1021 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1022 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1023 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1026 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1028 if (r_glsl_permutation->loc_AmbientColor >= 0)
1029 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1030 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1031 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1032 if (r_glsl_permutation->loc_SpecularColor >= 0)
1033 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1034 if (r_glsl_permutation->loc_LightDir >= 0)
1035 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1039 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1040 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1041 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1043 nmap = rsurface.texture->currentskinframe->nmap;
1044 if (gl_lightmaps.integer)
1045 nmap = r_texture_blanknormalmap;
1046 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1047 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1048 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1049 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1050 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1051 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1052 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1053 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1054 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1055 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1056 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1057 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1058 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1060 // The formula used is actually:
1061 // color.rgb *= SceneBrightness;
1062 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1063 // I simplify that to
1064 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1065 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1067 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1068 // and do [[calculations]] here in the engine
1069 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1070 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1073 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1074 if (r_glsl_permutation->loc_FogColor >= 0)
1076 // additive passes are only darkened by fog, not tinted
1077 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1078 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1080 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1082 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1083 if (r_glsl_permutation->loc_Color_Pants >= 0)
1085 if (rsurface.texture->currentskinframe->pants)
1086 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1088 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1090 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1092 if (rsurface.texture->currentskinframe->shirt)
1093 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1095 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1097 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1098 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1099 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1104 void R_SwitchSurfaceShader(int permutation)
1106 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1108 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1110 qglUseProgramObjectARB(r_glsl_permutation->program);
1115 #define SKINFRAME_HASH 1024
1119 int loadsequence; // incremented each level change
1120 memexpandablearray_t array;
1121 skinframe_t *hash[SKINFRAME_HASH];
1125 void R_SkinFrame_PrepareForPurge(void)
1127 r_skinframe.loadsequence++;
1128 // wrap it without hitting zero
1129 if (r_skinframe.loadsequence >= 200)
1130 r_skinframe.loadsequence = 1;
1133 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1137 // mark the skinframe as used for the purging code
1138 skinframe->loadsequence = r_skinframe.loadsequence;
1141 void R_SkinFrame_Purge(void)
1145 for (i = 0;i < SKINFRAME_HASH;i++)
1147 for (s = r_skinframe.hash[i];s;s = s->next)
1149 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1151 if (s->base == r_texture_notexture) s->base = NULL;
1152 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1153 if (s->merged == s->base) s->merged = NULL;
1154 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1155 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1156 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1157 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1158 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1159 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1160 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1161 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1162 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1163 s->loadsequence = 0;
1169 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1173 char basename[MAX_QPATH];
1175 Image_StripImageExtension(name, basename, sizeof(basename));
1177 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1178 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1179 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1185 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1186 memset(item, 0, sizeof(*item));
1187 strlcpy(item->basename, basename, sizeof(item->basename));
1188 item->textureflags = textureflags;
1189 item->comparewidth = comparewidth;
1190 item->compareheight = compareheight;
1191 item->comparecrc = comparecrc;
1192 item->next = r_skinframe.hash[hashindex];
1193 r_skinframe.hash[hashindex] = item;
1195 R_SkinFrame_MarkUsed(item);
1199 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1201 // FIXME: it should be possible to disable loading various layers using
1202 // cvars, to prevent wasted loading time and memory usage if the user does
1204 qboolean loadnormalmap = true;
1205 qboolean loadgloss = true;
1206 qboolean loadpantsandshirt = true;
1207 qboolean loadglow = true;
1209 unsigned char *pixels;
1210 unsigned char *bumppixels;
1211 unsigned char *basepixels = NULL;
1212 int basepixels_width;
1213 int basepixels_height;
1214 skinframe_t *skinframe;
1216 if (cls.state == ca_dedicated)
1219 // return an existing skinframe if already loaded
1220 // if loading of the first image fails, don't make a new skinframe as it
1221 // would cause all future lookups of this to be missing
1222 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1223 if (skinframe && skinframe->base)
1226 basepixels = loadimagepixels(name, complain, 0, 0);
1227 if (basepixels == NULL)
1230 // we've got some pixels to store, so really allocate this new texture now
1232 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1233 skinframe->stain = NULL;
1234 skinframe->merged = NULL;
1235 skinframe->base = r_texture_notexture;
1236 skinframe->pants = NULL;
1237 skinframe->shirt = NULL;
1238 skinframe->nmap = r_texture_blanknormalmap;
1239 skinframe->gloss = NULL;
1240 skinframe->glow = NULL;
1241 skinframe->fog = NULL;
1243 basepixels_width = image_width;
1244 basepixels_height = image_height;
1245 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1247 if (textureflags & TEXF_ALPHA)
1249 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1250 if (basepixels[j] < 255)
1252 if (j < basepixels_width * basepixels_height * 4)
1254 // has transparent pixels
1255 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1256 for (j = 0;j < image_width * image_height * 4;j += 4)
1261 pixels[j+3] = basepixels[j+3];
1263 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1268 // _norm is the name used by tenebrae and has been adopted as standard
1271 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1273 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1277 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1279 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1280 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1281 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1283 Mem_Free(bumppixels);
1285 else if (r_shadow_bumpscale_basetexture.value > 0)
1287 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1288 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1289 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1293 // _luma is supported for tenebrae compatibility
1294 // (I think it's a very stupid name, but oh well)
1295 // _glow is the preferred name
1296 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 & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1297 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 & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1298 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 & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1299 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 & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1302 Mem_Free(basepixels);
1307 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)
1312 for (i = 0;i < width*height;i++)
1313 if (((unsigned char *)&palette[in[i]])[3] > 0)
1315 if (i == width*height)
1318 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1321 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)
1324 unsigned char *temp1, *temp2;
1325 skinframe_t *skinframe;
1327 if (cls.state == ca_dedicated)
1330 // if already loaded just return it, otherwise make a new skinframe
1331 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1332 if (skinframe && skinframe->base)
1335 skinframe->stain = NULL;
1336 skinframe->merged = NULL;
1337 skinframe->base = r_texture_notexture;
1338 skinframe->pants = NULL;
1339 skinframe->shirt = NULL;
1340 skinframe->nmap = r_texture_blanknormalmap;
1341 skinframe->gloss = NULL;
1342 skinframe->glow = NULL;
1343 skinframe->fog = NULL;
1345 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1349 if (bitsperpixel == 32)
1351 if (r_shadow_bumpscale_basetexture.value > 0)
1353 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1354 temp2 = temp1 + width * height * 4;
1355 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1356 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1359 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1360 if (textureflags & TEXF_ALPHA)
1362 for (i = 3;i < width * height * 4;i += 4)
1363 if (skindata[i] < 255)
1365 if (i < width * height * 4)
1367 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1368 memcpy(fogpixels, skindata, width * height * 4);
1369 for (i = 0;i < width * height * 4;i += 4)
1370 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1371 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1372 Mem_Free(fogpixels);
1376 else if (bitsperpixel == 8)
1378 if (r_shadow_bumpscale_basetexture.value > 0)
1380 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1381 temp2 = temp1 + width * height * 4;
1382 if (bitsperpixel == 32)
1383 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1386 // use either a custom palette or the quake palette
1387 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1388 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1390 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1393 // use either a custom palette, or the quake palette
1394 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all
1395 if (!palette && loadglowtexture)
1396 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1397 if (!palette && loadpantsandshirt)
1399 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1400 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1402 if (skinframe->pants || skinframe->shirt)
1403 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1404 if (textureflags & TEXF_ALPHA)
1406 // if not using a custom alphapalette, use the quake one
1408 alphapalette = palette_alpha;
1409 for (i = 0;i < width * height;i++)
1410 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1412 if (i < width * height)
1413 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1420 skinframe_t *R_SkinFrame_LoadMissing(void)
1422 skinframe_t *skinframe;
1424 if (cls.state == ca_dedicated)
1427 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1428 skinframe->stain = NULL;
1429 skinframe->merged = NULL;
1430 skinframe->base = r_texture_notexture;
1431 skinframe->pants = NULL;
1432 skinframe->shirt = NULL;
1433 skinframe->nmap = r_texture_blanknormalmap;
1434 skinframe->gloss = NULL;
1435 skinframe->glow = NULL;
1436 skinframe->fog = NULL;
1441 void gl_main_start(void)
1446 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1447 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1449 alpha = 1 - exp(r / ((double)x*(double)x));
1450 if (x == FOGMASKTABLEWIDTH - 1)
1452 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1455 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1456 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1458 // set up r_skinframe loading system for textures
1459 memset(&r_skinframe, 0, sizeof(r_skinframe));
1460 r_skinframe.loadsequence = 1;
1461 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1463 r_main_texturepool = R_AllocTexturePool();
1464 R_BuildBlankTextures();
1466 if (gl_texturecubemap)
1469 R_BuildNormalizationCube();
1471 R_BuildFogTexture();
1472 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1473 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1474 memset(&r_svbsp, 0, sizeof (r_svbsp));
1477 void gl_main_shutdown(void)
1479 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1480 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1482 // clear out the r_skinframe state
1483 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1484 memset(&r_skinframe, 0, sizeof(r_skinframe));
1487 Mem_Free(r_svbsp.nodes);
1488 memset(&r_svbsp, 0, sizeof (r_svbsp));
1489 R_FreeTexturePool(&r_main_texturepool);
1490 r_texture_blanknormalmap = NULL;
1491 r_texture_white = NULL;
1492 r_texture_grey128 = NULL;
1493 r_texture_black = NULL;
1494 r_texture_whitecube = NULL;
1495 r_texture_normalizationcube = NULL;
1496 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1500 extern void CL_ParseEntityLump(char *entitystring);
1501 void gl_main_newmap(void)
1503 // FIXME: move this code to client
1505 char *entities, entname[MAX_QPATH];
1508 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1509 l = (int)strlen(entname) - 4;
1510 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1512 memcpy(entname + l, ".ent", 5);
1513 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1515 CL_ParseEntityLump(entities);
1520 if (cl.worldmodel->brush.entities)
1521 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1525 void GL_Main_Init(void)
1527 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1529 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1530 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1531 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1532 if (gamemode == GAME_NEHAHRA)
1534 Cvar_RegisterVariable (&gl_fogenable);
1535 Cvar_RegisterVariable (&gl_fogdensity);
1536 Cvar_RegisterVariable (&gl_fogred);
1537 Cvar_RegisterVariable (&gl_foggreen);
1538 Cvar_RegisterVariable (&gl_fogblue);
1539 Cvar_RegisterVariable (&gl_fogstart);
1540 Cvar_RegisterVariable (&gl_fogend);
1542 Cvar_RegisterVariable(&r_depthfirst);
1543 Cvar_RegisterVariable(&r_nearclip);
1544 Cvar_RegisterVariable(&r_showbboxes);
1545 Cvar_RegisterVariable(&r_showsurfaces);
1546 Cvar_RegisterVariable(&r_showtris);
1547 Cvar_RegisterVariable(&r_shownormals);
1548 Cvar_RegisterVariable(&r_showlighting);
1549 Cvar_RegisterVariable(&r_showshadowvolumes);
1550 Cvar_RegisterVariable(&r_showcollisionbrushes);
1551 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1552 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1553 Cvar_RegisterVariable(&r_showdisabledepthtest);
1554 Cvar_RegisterVariable(&r_drawportals);
1555 Cvar_RegisterVariable(&r_drawentities);
1556 Cvar_RegisterVariable(&r_cullentities_trace);
1557 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1558 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1559 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1560 Cvar_RegisterVariable(&r_drawviewmodel);
1561 Cvar_RegisterVariable(&r_speeds);
1562 Cvar_RegisterVariable(&r_fullbrights);
1563 Cvar_RegisterVariable(&r_wateralpha);
1564 Cvar_RegisterVariable(&r_dynamic);
1565 Cvar_RegisterVariable(&r_fullbright);
1566 Cvar_RegisterVariable(&r_shadows);
1567 Cvar_RegisterVariable(&r_shadows_throwdistance);
1568 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1569 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1570 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1571 Cvar_RegisterVariable(&r_textureunits);
1572 Cvar_RegisterVariable(&r_glsl);
1573 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1574 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1575 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1576 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1577 Cvar_RegisterVariable(&r_lerpsprites);
1578 Cvar_RegisterVariable(&r_lerpmodels);
1579 Cvar_RegisterVariable(&r_waterscroll);
1580 Cvar_RegisterVariable(&r_bloom);
1581 Cvar_RegisterVariable(&r_bloom_colorscale);
1582 Cvar_RegisterVariable(&r_bloom_brighten);
1583 Cvar_RegisterVariable(&r_bloom_blur);
1584 Cvar_RegisterVariable(&r_bloom_resolution);
1585 Cvar_RegisterVariable(&r_bloom_colorexponent);
1586 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1587 Cvar_RegisterVariable(&r_hdr);
1588 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1589 Cvar_RegisterVariable(&r_glsl_contrastboost);
1590 Cvar_RegisterVariable(&r_hdr_glowintensity);
1591 Cvar_RegisterVariable(&r_hdr_range);
1592 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1593 Cvar_RegisterVariable(&developer_texturelogging);
1594 Cvar_RegisterVariable(&gl_lightmaps);
1595 Cvar_RegisterVariable(&r_test);
1596 Cvar_RegisterVariable(&r_batchmode);
1597 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1598 Cvar_SetValue("r_fullbrights", 0);
1599 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1602 extern void R_Textures_Init(void);
1603 extern void GL_Draw_Init(void);
1604 extern void GL_Main_Init(void);
1605 extern void R_Shadow_Init(void);
1606 extern void R_Sky_Init(void);
1607 extern void GL_Surf_Init(void);
1608 extern void R_Light_Init(void);
1609 extern void R_Particles_Init(void);
1610 extern void R_Explosion_Init(void);
1611 extern void gl_backend_init(void);
1612 extern void Sbar_Init(void);
1613 extern void R_LightningBeams_Init(void);
1614 extern void Mod_RenderInit(void);
1616 void Render_Init(void)
1629 R_LightningBeams_Init();
1638 extern char *ENGINE_EXTENSIONS;
1641 VID_CheckExtensions();
1643 // LordHavoc: report supported extensions
1644 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1646 // clear to black (loading plaque will be seen over this)
1648 qglClearColor(0,0,0,1);CHECKGLERROR
1649 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1652 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1656 for (i = 0;i < 4;i++)
1658 p = r_view.frustum + i;
1663 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1667 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1671 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1675 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1679 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1683 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1687 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1691 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1699 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1703 for (i = 0;i < numplanes;i++)
1710 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1714 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1718 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1722 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1726 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1730 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1734 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1738 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1746 //==================================================================================
1748 static void R_UpdateEntityLighting(entity_render_t *ent)
1750 vec3_t tempdiffusenormal;
1752 // fetch the lighting from the worldmodel data
1753 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));
1754 VectorClear(ent->modellight_diffuse);
1755 VectorClear(tempdiffusenormal);
1756 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1759 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1760 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1763 VectorSet(ent->modellight_ambient, 1, 1, 1);
1765 // move the light direction into modelspace coordinates for lighting code
1766 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1767 if(VectorLength2(ent->modellight_lightdir) > 0)
1769 VectorNormalize(ent->modellight_lightdir);
1773 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1776 // scale ambient and directional light contributions according to rendering variables
1777 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1778 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1779 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1780 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1781 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1782 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1785 static void R_View_UpdateEntityVisible (void)
1788 entity_render_t *ent;
1790 if (!r_drawentities.integer)
1793 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1794 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1796 // worldmodel can check visibility
1797 for (i = 0;i < r_refdef.numentities;i++)
1799 ent = r_refdef.entities[i];
1800 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));
1802 if(r_cullentities_trace.integer)
1804 for (i = 0;i < r_refdef.numentities;i++)
1806 ent = r_refdef.entities[i];
1807 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1809 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1810 ent->last_trace_visibility = realtime;
1811 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1812 r_viewcache.entityvisible[i] = 0;
1819 // no worldmodel or it can't check visibility
1820 for (i = 0;i < r_refdef.numentities;i++)
1822 ent = r_refdef.entities[i];
1823 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1827 // update entity lighting (even on hidden entities for r_shadows)
1828 for (i = 0;i < r_refdef.numentities;i++)
1829 R_UpdateEntityLighting(r_refdef.entities[i]);
1832 // only used if skyrendermasked, and normally returns false
1833 int R_DrawBrushModelsSky (void)
1836 entity_render_t *ent;
1838 if (!r_drawentities.integer)
1842 for (i = 0;i < r_refdef.numentities;i++)
1844 if (!r_viewcache.entityvisible[i])
1846 ent = r_refdef.entities[i];
1847 if (!ent->model || !ent->model->DrawSky)
1849 ent->model->DrawSky(ent);
1855 void R_DrawNoModel(entity_render_t *ent);
1856 void R_DrawModels(void)
1859 entity_render_t *ent;
1861 if (!r_drawentities.integer)
1864 for (i = 0;i < r_refdef.numentities;i++)
1866 if (!r_viewcache.entityvisible[i])
1868 ent = r_refdef.entities[i];
1869 r_refdef.stats.entities++;
1870 if (ent->model && ent->model->Draw != NULL)
1871 ent->model->Draw(ent);
1877 void R_DrawModelsDepth(void)
1880 entity_render_t *ent;
1882 if (!r_drawentities.integer)
1885 for (i = 0;i < r_refdef.numentities;i++)
1887 if (!r_viewcache.entityvisible[i])
1889 ent = r_refdef.entities[i];
1890 r_refdef.stats.entities++;
1891 if (ent->model && ent->model->DrawDepth != NULL)
1892 ent->model->DrawDepth(ent);
1896 static void R_View_SetFrustum(void)
1898 double slopex, slopey;
1900 // break apart the view matrix into vectors for various purposes
1901 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1902 VectorNegate(r_view.left, r_view.right);
1905 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1906 r_view.frustum[0].normal[1] = 0 - 0;
1907 r_view.frustum[0].normal[2] = -1 - 0;
1908 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1909 r_view.frustum[1].normal[1] = 0 + 0;
1910 r_view.frustum[1].normal[2] = -1 + 0;
1911 r_view.frustum[2].normal[0] = 0 - 0;
1912 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1913 r_view.frustum[2].normal[2] = -1 - 0;
1914 r_view.frustum[3].normal[0] = 0 + 0;
1915 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1916 r_view.frustum[3].normal[2] = -1 + 0;
1920 zNear = r_refdef.nearclip;
1921 nudge = 1.0 - 1.0 / (1<<23);
1922 r_view.frustum[4].normal[0] = 0 - 0;
1923 r_view.frustum[4].normal[1] = 0 - 0;
1924 r_view.frustum[4].normal[2] = -1 - -nudge;
1925 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1926 r_view.frustum[5].normal[0] = 0 + 0;
1927 r_view.frustum[5].normal[1] = 0 + 0;
1928 r_view.frustum[5].normal[2] = -1 + -nudge;
1929 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1935 r_view.frustum[0].normal[0] = m[3] - m[0];
1936 r_view.frustum[0].normal[1] = m[7] - m[4];
1937 r_view.frustum[0].normal[2] = m[11] - m[8];
1938 r_view.frustum[0].dist = m[15] - m[12];
1940 r_view.frustum[1].normal[0] = m[3] + m[0];
1941 r_view.frustum[1].normal[1] = m[7] + m[4];
1942 r_view.frustum[1].normal[2] = m[11] + m[8];
1943 r_view.frustum[1].dist = m[15] + m[12];
1945 r_view.frustum[2].normal[0] = m[3] - m[1];
1946 r_view.frustum[2].normal[1] = m[7] - m[5];
1947 r_view.frustum[2].normal[2] = m[11] - m[9];
1948 r_view.frustum[2].dist = m[15] - m[13];
1950 r_view.frustum[3].normal[0] = m[3] + m[1];
1951 r_view.frustum[3].normal[1] = m[7] + m[5];
1952 r_view.frustum[3].normal[2] = m[11] + m[9];
1953 r_view.frustum[3].dist = m[15] + m[13];
1955 r_view.frustum[4].normal[0] = m[3] - m[2];
1956 r_view.frustum[4].normal[1] = m[7] - m[6];
1957 r_view.frustum[4].normal[2] = m[11] - m[10];
1958 r_view.frustum[4].dist = m[15] - m[14];
1960 r_view.frustum[5].normal[0] = m[3] + m[2];
1961 r_view.frustum[5].normal[1] = m[7] + m[6];
1962 r_view.frustum[5].normal[2] = m[11] + m[10];
1963 r_view.frustum[5].dist = m[15] + m[14];
1968 if (r_view.useperspective)
1970 slopex = 1.0 / r_view.frustum_x;
1971 slopey = 1.0 / r_view.frustum_y;
1972 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1973 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1974 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1975 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1976 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1978 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1979 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1980 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1981 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1982 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1984 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1985 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1986 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1987 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1988 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1992 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
1993 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
1994 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
1995 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
1996 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1997 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
1998 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
1999 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2000 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2001 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2004 PlaneClassify(&r_view.frustum[0]);
2005 PlaneClassify(&r_view.frustum[1]);
2006 PlaneClassify(&r_view.frustum[2]);
2007 PlaneClassify(&r_view.frustum[3]);
2008 PlaneClassify(&r_view.frustum[4]);
2010 // LordHavoc: note to all quake engine coders, Quake had a special case
2011 // for 90 degrees which assumed a square view (wrong), so I removed it,
2012 // Quake2 has it disabled as well.
2014 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2015 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2016 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2017 //PlaneClassify(&frustum[0]);
2019 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2020 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2021 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2022 //PlaneClassify(&frustum[1]);
2024 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2025 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2026 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2027 //PlaneClassify(&frustum[2]);
2029 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2030 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2031 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2032 //PlaneClassify(&frustum[3]);
2035 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2036 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2037 //PlaneClassify(&frustum[4]);
2040 void R_View_Update(void)
2042 R_View_SetFrustum();
2043 R_View_WorldVisibility();
2044 R_View_UpdateEntityVisible();
2047 void R_SetupView(const matrix4x4_t *matrix)
2049 if (!r_view.useperspective)
2050 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);
2051 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2052 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2054 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2056 GL_SetupView_Orientation_FromEntity(matrix);
2059 void R_ResetViewRendering2D(void)
2061 if (gl_support_fragment_shader)
2063 qglUseProgramObjectARB(0);CHECKGLERROR
2068 // GL is weird because it's bottom to top, r_view.y is top to bottom
2069 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2070 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2071 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2072 GL_Color(1, 1, 1, 1);
2073 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2074 GL_BlendFunc(GL_ONE, GL_ZERO);
2075 GL_AlphaTest(false);
2076 GL_ScissorTest(false);
2077 GL_DepthMask(false);
2078 GL_DepthRange(0, 1);
2079 GL_DepthTest(false);
2080 R_Mesh_Matrix(&identitymatrix);
2081 R_Mesh_ResetTextureState();
2082 GL_PolygonOffset(0, 0);
2083 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2084 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2085 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2086 qglStencilMask(~0);CHECKGLERROR
2087 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2088 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2089 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2092 void R_ResetViewRendering3D(void)
2094 if (gl_support_fragment_shader)
2096 qglUseProgramObjectARB(0);CHECKGLERROR
2101 // GL is weird because it's bottom to top, r_view.y is top to bottom
2102 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2103 R_SetupView(&r_view.matrix);
2104 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2105 GL_Color(1, 1, 1, 1);
2106 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2107 GL_BlendFunc(GL_ONE, GL_ZERO);
2108 GL_AlphaTest(false);
2109 GL_ScissorTest(true);
2111 GL_DepthRange(0, 1);
2113 R_Mesh_Matrix(&identitymatrix);
2114 R_Mesh_ResetTextureState();
2115 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2116 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2117 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2118 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2119 qglStencilMask(~0);CHECKGLERROR
2120 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2121 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2122 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2126 R_Bloom_SetupShader(
2128 "// written by Forest 'LordHavoc' Hale\n"
2130 "// common definitions between vertex shader and fragment shader:\n"
2132 "#ifdef __GLSL_CG_DATA_TYPES\n"
2133 "#define myhalf half\n"
2134 "#define myhvec2 hvec2\n"
2135 "#define myhvec3 hvec3\n"
2136 "#define myhvec4 hvec4\n"
2138 "#define myhalf float\n"
2139 "#define myhvec2 vec2\n"
2140 "#define myhvec3 vec3\n"
2141 "#define myhvec4 vec4\n"
2144 "varying vec2 ScreenTexCoord;\n"
2145 "varying vec2 BloomTexCoord;\n"
2150 "// vertex shader specific:\n"
2151 "#ifdef VERTEX_SHADER\n"
2155 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2156 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2157 " // transform vertex to camera space, using ftransform to match non-VS\n"
2159 " gl_Position = ftransform();\n"
2162 "#endif // VERTEX_SHADER\n"
2167 "// fragment shader specific:\n"
2168 "#ifdef FRAGMENT_SHADER\n"
2173 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2174 " for (x = -BLUR_X;x <= BLUR_X;x++)
2175 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2176 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2177 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2178 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2180 " gl_FragColor = vec4(color);\n"
2183 "#endif // FRAGMENT_SHADER\n"
2186 void R_RenderScene(void);
2188 void R_Bloom_StartFrame(void)
2190 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2192 // set bloomwidth and bloomheight to the bloom resolution that will be
2193 // used (often less than the screen resolution for faster rendering)
2194 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2195 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2196 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2198 // calculate desired texture sizes
2199 if (gl_support_arb_texture_non_power_of_two)
2201 screentexturewidth = r_view.width;
2202 screentextureheight = r_view.height;
2203 bloomtexturewidth = r_bloomstate.bloomwidth;
2204 bloomtextureheight = r_bloomstate.bloomheight;
2208 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2209 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2210 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2211 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2216 screentexturewidth = screentextureheight = 0;
2218 else if (r_bloom.integer)
2223 screentexturewidth = screentextureheight = 0;
2224 bloomtexturewidth = bloomtextureheight = 0;
2227 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)
2229 // can't use bloom if the parameters are too weird
2230 // can't use bloom if the card does not support the texture size
2231 if (r_bloomstate.texture_screen)
2232 R_FreeTexture(r_bloomstate.texture_screen);
2233 if (r_bloomstate.texture_bloom)
2234 R_FreeTexture(r_bloomstate.texture_bloom);
2235 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2239 r_bloomstate.enabled = true;
2240 r_bloomstate.hdr = r_hdr.integer != 0;
2242 // allocate textures as needed
2243 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2245 if (r_bloomstate.texture_screen)
2246 R_FreeTexture(r_bloomstate.texture_screen);
2247 r_bloomstate.texture_screen = NULL;
2248 r_bloomstate.screentexturewidth = screentexturewidth;
2249 r_bloomstate.screentextureheight = screentextureheight;
2250 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2251 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);
2253 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2255 if (r_bloomstate.texture_bloom)
2256 R_FreeTexture(r_bloomstate.texture_bloom);
2257 r_bloomstate.texture_bloom = NULL;
2258 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2259 r_bloomstate.bloomtextureheight = bloomtextureheight;
2260 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2261 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);
2264 // set up a texcoord array for the full resolution screen image
2265 // (we have to keep this around to copy back during final render)
2266 r_bloomstate.screentexcoord2f[0] = 0;
2267 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2268 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2269 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2270 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2271 r_bloomstate.screentexcoord2f[5] = 0;
2272 r_bloomstate.screentexcoord2f[6] = 0;
2273 r_bloomstate.screentexcoord2f[7] = 0;
2275 // set up a texcoord array for the reduced resolution bloom image
2276 // (which will be additive blended over the screen image)
2277 r_bloomstate.bloomtexcoord2f[0] = 0;
2278 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2279 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2280 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2281 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2282 r_bloomstate.bloomtexcoord2f[5] = 0;
2283 r_bloomstate.bloomtexcoord2f[6] = 0;
2284 r_bloomstate.bloomtexcoord2f[7] = 0;
2287 void R_Bloom_CopyScreenTexture(float colorscale)
2289 r_refdef.stats.bloom++;
2291 R_ResetViewRendering2D();
2292 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2293 R_Mesh_ColorPointer(NULL, 0, 0);
2294 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2295 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2297 // copy view into the screen texture
2298 GL_ActiveTexture(0);
2300 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
2301 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2303 // now scale it down to the bloom texture size
2305 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2306 GL_BlendFunc(GL_ONE, GL_ZERO);
2307 GL_Color(colorscale, colorscale, colorscale, 1);
2308 // TODO: optimize with multitexture or GLSL
2309 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2310 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2312 // we now have a bloom image in the framebuffer
2313 // copy it into the bloom image texture for later processing
2314 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2315 GL_ActiveTexture(0);
2317 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
2318 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2321 void R_Bloom_CopyHDRTexture(void)
2323 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2324 GL_ActiveTexture(0);
2326 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
2327 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2330 void R_Bloom_MakeTexture(void)
2333 float xoffset, yoffset, r, brighten;
2335 r_refdef.stats.bloom++;
2337 R_ResetViewRendering2D();
2338 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2339 R_Mesh_ColorPointer(NULL, 0, 0);
2341 // we have a bloom image in the framebuffer
2343 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2345 for (x = 1;x < r_bloom_colorexponent.value;)
2348 r = bound(0, r_bloom_colorexponent.value / x, 1);
2349 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2350 GL_Color(r, r, r, 1);
2351 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2352 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2353 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2354 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2356 // copy the vertically blurred bloom view to a texture
2357 GL_ActiveTexture(0);
2359 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
2360 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2363 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2364 brighten = r_bloom_brighten.value;
2366 brighten *= r_hdr_range.value;
2367 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2368 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2370 for (dir = 0;dir < 2;dir++)
2372 // blend on at multiple vertical offsets to achieve a vertical blur
2373 // TODO: do offset blends using GLSL
2374 GL_BlendFunc(GL_ONE, GL_ZERO);
2375 for (x = -range;x <= range;x++)
2377 if (!dir){xoffset = 0;yoffset = x;}
2378 else {xoffset = x;yoffset = 0;}
2379 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2380 yoffset /= (float)r_bloomstate.bloomtextureheight;
2381 // compute a texcoord array with the specified x and y offset
2382 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2383 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2384 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2385 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2386 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2387 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2388 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2389 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2390 // this r value looks like a 'dot' particle, fading sharply to
2391 // black at the edges
2392 // (probably not realistic but looks good enough)
2393 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2394 //r = (dir ? 1.0f : brighten)/(range*2+1);
2395 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2396 GL_Color(r, r, r, 1);
2397 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2398 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2399 GL_BlendFunc(GL_ONE, GL_ONE);
2402 // copy the vertically blurred bloom view to a texture
2403 GL_ActiveTexture(0);
2405 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
2406 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2409 // apply subtract last
2410 // (just like it would be in a GLSL shader)
2411 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2413 GL_BlendFunc(GL_ONE, GL_ZERO);
2414 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2415 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2416 GL_Color(1, 1, 1, 1);
2417 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2418 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2420 GL_BlendFunc(GL_ONE, GL_ONE);
2421 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2422 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2423 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2424 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2425 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2426 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2427 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2429 // copy the darkened bloom view to a texture
2430 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2431 GL_ActiveTexture(0);
2433 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
2434 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2438 void R_HDR_RenderBloomTexture(void)
2440 int oldwidth, oldheight;
2442 oldwidth = r_view.width;
2443 oldheight = r_view.height;
2444 r_view.width = r_bloomstate.bloomwidth;
2445 r_view.height = r_bloomstate.bloomheight;
2447 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2448 // TODO: add exposure compensation features
2449 // TODO: add fp16 framebuffer support
2451 r_view.showdebug = false;
2452 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2454 r_view.colorscale /= r_hdr_range.value;
2456 r_view.showdebug = true;
2458 R_ResetViewRendering2D();
2460 R_Bloom_CopyHDRTexture();
2461 R_Bloom_MakeTexture();
2463 R_ResetViewRendering3D();
2466 if (r_timereport_active)
2467 R_TimeReport("clear");
2470 // restore the view settings
2471 r_view.width = oldwidth;
2472 r_view.height = oldheight;
2475 static void R_BlendView(void)
2477 if (r_bloomstate.enabled && r_bloomstate.hdr)
2479 // render high dynamic range bloom effect
2480 // the bloom texture was made earlier this render, so we just need to
2481 // blend it onto the screen...
2482 R_ResetViewRendering2D();
2483 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2484 R_Mesh_ColorPointer(NULL, 0, 0);
2485 GL_Color(1, 1, 1, 1);
2486 GL_BlendFunc(GL_ONE, GL_ONE);
2487 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2488 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2489 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2490 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2492 else if (r_bloomstate.enabled)
2494 // render simple bloom effect
2495 // copy the screen and shrink it and darken it for the bloom process
2496 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2497 // make the bloom texture
2498 R_Bloom_MakeTexture();
2499 // put the original screen image back in place and blend the bloom
2501 R_ResetViewRendering2D();
2502 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2503 R_Mesh_ColorPointer(NULL, 0, 0);
2504 GL_Color(1, 1, 1, 1);
2505 GL_BlendFunc(GL_ONE, GL_ZERO);
2506 // do both in one pass if possible
2507 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2508 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2509 if (r_textureunits.integer >= 2 && gl_combine.integer)
2511 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2512 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2513 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2517 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2518 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2519 // now blend on the bloom texture
2520 GL_BlendFunc(GL_ONE, GL_ONE);
2521 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2522 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2524 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2525 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2527 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2529 // apply a color tint to the whole view
2530 R_ResetViewRendering2D();
2531 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2532 R_Mesh_ColorPointer(NULL, 0, 0);
2533 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2534 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2535 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2539 void R_RenderScene(void);
2541 matrix4x4_t r_waterscrollmatrix;
2543 void R_UpdateVariables(void)
2547 r_refdef.farclip = 4096;
2548 if (r_refdef.worldmodel)
2549 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2550 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2552 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2553 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2554 r_refdef.polygonfactor = 0;
2555 r_refdef.polygonoffset = 0;
2556 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2557 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2559 r_refdef.rtworld = r_shadow_realtime_world.integer;
2560 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2561 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2562 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2563 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2564 if (r_showsurfaces.integer)
2566 r_refdef.rtworld = false;
2567 r_refdef.rtworldshadows = false;
2568 r_refdef.rtdlight = false;
2569 r_refdef.rtdlightshadows = false;
2570 r_refdef.lightmapintensity = 0;
2573 if (gamemode == GAME_NEHAHRA)
2575 if (gl_fogenable.integer)
2577 r_refdef.oldgl_fogenable = true;
2578 r_refdef.fog_density = gl_fogdensity.value;
2579 r_refdef.fog_red = gl_fogred.value;
2580 r_refdef.fog_green = gl_foggreen.value;
2581 r_refdef.fog_blue = gl_fogblue.value;
2583 else if (r_refdef.oldgl_fogenable)
2585 r_refdef.oldgl_fogenable = false;
2586 r_refdef.fog_density = 0;
2587 r_refdef.fog_red = 0;
2588 r_refdef.fog_green = 0;
2589 r_refdef.fog_blue = 0;
2592 if (r_refdef.fog_density)
2594 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2595 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2596 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2598 if (r_refdef.fog_density)
2600 r_refdef.fogenabled = true;
2601 // this is the point where the fog reaches 0.9986 alpha, which we
2602 // consider a good enough cutoff point for the texture
2603 // (0.9986 * 256 == 255.6)
2604 r_refdef.fogrange = 400 / r_refdef.fog_density;
2605 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2606 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2607 // fog color was already set
2610 r_refdef.fogenabled = false;
2618 void R_RenderView(void)
2620 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2621 return; //Host_Error ("R_RenderView: NULL worldmodel");
2623 R_Shadow_UpdateWorldLightSelection();
2626 if (r_timereport_active)
2627 R_TimeReport("setup");
2630 if (r_timereport_active)
2631 R_TimeReport("visibility");
2633 R_ResetViewRendering3D();
2636 if (r_timereport_active)
2637 R_TimeReport("clear");
2639 R_Bloom_StartFrame();
2641 r_view.showdebug = true;
2643 // this produces a bloom texture to be used in R_BlendView() later
2645 R_HDR_RenderBloomTexture();
2647 r_view.colorscale = r_hdr_scenebrightness.value;
2651 if (r_timereport_active)
2652 R_TimeReport("blendview");
2654 GL_Scissor(0, 0, vid.width, vid.height);
2655 GL_ScissorTest(false);
2659 extern void R_DrawLightningBeams (void);
2660 extern void VM_CL_AddPolygonsToMeshQueue (void);
2661 extern void R_DrawPortals (void);
2662 extern cvar_t cl_locs_show;
2663 static void R_DrawLocs(void);
2664 static void R_DrawEntityBBoxes(void);
2665 void R_RenderScene(void)
2667 // don't let sound skip if going slow
2668 if (r_refdef.extraupdate)
2671 R_ResetViewRendering3D();
2673 R_MeshQueue_BeginScene();
2677 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);
2679 if (cl.csqc_vidvars.drawworld)
2681 // don't let sound skip if going slow
2682 if (r_refdef.extraupdate)
2685 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2687 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2688 if (r_timereport_active)
2689 R_TimeReport("worldsky");
2692 if (R_DrawBrushModelsSky() && r_timereport_active)
2693 R_TimeReport("bmodelsky");
2696 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
2698 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
2699 if (r_timereport_active)
2700 R_TimeReport("worlddepth");
2702 if (r_depthfirst.integer >= 2)
2704 R_DrawModelsDepth();
2705 if (r_timereport_active)
2706 R_TimeReport("modeldepth");
2709 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2711 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2712 if (r_timereport_active)
2713 R_TimeReport("world");
2716 // don't let sound skip if going slow
2717 if (r_refdef.extraupdate)
2721 if (r_timereport_active)
2722 R_TimeReport("models");
2724 // don't let sound skip if going slow
2725 if (r_refdef.extraupdate)
2728 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2730 R_DrawModelShadows();
2732 R_ResetViewRendering3D();
2734 // don't let sound skip if going slow
2735 if (r_refdef.extraupdate)
2739 R_ShadowVolumeLighting(false);
2740 if (r_timereport_active)
2741 R_TimeReport("rtlights");
2743 // don't let sound skip if going slow
2744 if (r_refdef.extraupdate)
2747 if (cl.csqc_vidvars.drawworld)
2749 R_DrawLightningBeams();
2750 if (r_timereport_active)
2751 R_TimeReport("lightning");
2754 if (r_timereport_active)
2755 R_TimeReport("particles");
2758 if (r_timereport_active)
2759 R_TimeReport("explosions");
2762 if (gl_support_fragment_shader)
2764 qglUseProgramObjectARB(0);CHECKGLERROR
2766 VM_CL_AddPolygonsToMeshQueue();
2768 if (r_view.showdebug)
2770 if (cl_locs_show.integer)
2773 if (r_timereport_active)
2774 R_TimeReport("showlocs");
2777 if (r_drawportals.integer)
2780 if (r_timereport_active)
2781 R_TimeReport("portals");
2784 if (r_showbboxes.value > 0)
2786 R_DrawEntityBBoxes();
2787 if (r_timereport_active)
2788 R_TimeReport("bboxes");
2792 if (gl_support_fragment_shader)
2794 qglUseProgramObjectARB(0);CHECKGLERROR
2796 R_MeshQueue_RenderTransparent();
2797 if (r_timereport_active)
2798 R_TimeReport("drawtrans");
2800 if (gl_support_fragment_shader)
2802 qglUseProgramObjectARB(0);CHECKGLERROR
2805 if (cl.csqc_vidvars.drawworld)
2808 if (r_timereport_active)
2809 R_TimeReport("coronas");
2812 // don't let sound skip if going slow
2813 if (r_refdef.extraupdate)
2816 R_ResetViewRendering2D();
2819 static const int bboxelements[36] =
2829 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2832 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2833 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2834 GL_DepthMask(false);
2835 GL_DepthRange(0, 1);
2836 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2837 R_Mesh_Matrix(&identitymatrix);
2838 R_Mesh_ResetTextureState();
2840 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2841 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2842 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2843 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2844 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2845 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2846 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2847 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2848 R_FillColors(color4f, 8, cr, cg, cb, ca);
2849 if (r_refdef.fogenabled)
2851 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2853 f1 = FogPoint_World(v);
2855 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2856 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2857 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2860 R_Mesh_VertexPointer(vertex3f, 0, 0);
2861 R_Mesh_ColorPointer(color4f, 0, 0);
2862 R_Mesh_ResetTextureState();
2863 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2866 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2870 prvm_edict_t *edict;
2871 // this function draws bounding boxes of server entities
2875 for (i = 0;i < numsurfaces;i++)
2877 edict = PRVM_EDICT_NUM(surfacelist[i]);
2878 switch ((int)edict->fields.server->solid)
2880 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2881 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2882 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2883 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2884 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2885 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2887 color[3] *= r_showbboxes.value;
2888 color[3] = bound(0, color[3], 1);
2889 GL_DepthTest(!r_showdisabledepthtest.integer);
2890 GL_CullFace(GL_BACK);
2891 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2896 static void R_DrawEntityBBoxes(void)
2899 prvm_edict_t *edict;
2901 // this function draws bounding boxes of server entities
2905 for (i = 0;i < prog->num_edicts;i++)
2907 edict = PRVM_EDICT_NUM(i);
2908 if (edict->priv.server->free)
2910 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2911 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2916 int nomodelelements[24] =
2928 float nomodelvertex3f[6*3] =
2938 float nomodelcolor4f[6*4] =
2940 0.0f, 0.0f, 0.5f, 1.0f,
2941 0.0f, 0.0f, 0.5f, 1.0f,
2942 0.0f, 0.5f, 0.0f, 1.0f,
2943 0.0f, 0.5f, 0.0f, 1.0f,
2944 0.5f, 0.0f, 0.0f, 1.0f,
2945 0.5f, 0.0f, 0.0f, 1.0f
2948 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2953 // this is only called once per entity so numsurfaces is always 1, and
2954 // surfacelist is always {0}, so this code does not handle batches
2955 R_Mesh_Matrix(&ent->matrix);
2957 if (ent->flags & EF_ADDITIVE)
2959 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2960 GL_DepthMask(false);
2962 else if (ent->alpha < 1)
2964 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2965 GL_DepthMask(false);
2969 GL_BlendFunc(GL_ONE, GL_ZERO);
2972 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2973 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2974 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2975 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2976 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2977 if (r_refdef.fogenabled)
2980 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2981 R_Mesh_ColorPointer(color4f, 0, 0);
2982 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2983 f1 = FogPoint_World(org);
2985 for (i = 0, c = color4f;i < 6;i++, c += 4)
2987 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2988 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2989 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2993 else if (ent->alpha != 1)
2995 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2996 R_Mesh_ColorPointer(color4f, 0, 0);
2997 for (i = 0, c = color4f;i < 6;i++, c += 4)
3001 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3002 R_Mesh_ResetTextureState();
3003 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3006 void R_DrawNoModel(entity_render_t *ent)
3009 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3010 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3011 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3013 // R_DrawNoModelCallback(ent, 0);
3016 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3018 vec3_t right1, right2, diff, normal;
3020 VectorSubtract (org2, org1, normal);
3022 // calculate 'right' vector for start
3023 VectorSubtract (r_view.origin, org1, diff);
3024 CrossProduct (normal, diff, right1);
3025 VectorNormalize (right1);
3027 // calculate 'right' vector for end
3028 VectorSubtract (r_view.origin, org2, diff);
3029 CrossProduct (normal, diff, right2);
3030 VectorNormalize (right2);
3032 vert[ 0] = org1[0] + width * right1[0];
3033 vert[ 1] = org1[1] + width * right1[1];
3034 vert[ 2] = org1[2] + width * right1[2];
3035 vert[ 3] = org1[0] - width * right1[0];
3036 vert[ 4] = org1[1] - width * right1[1];
3037 vert[ 5] = org1[2] - width * right1[2];
3038 vert[ 6] = org2[0] - width * right2[0];
3039 vert[ 7] = org2[1] - width * right2[1];
3040 vert[ 8] = org2[2] - width * right2[2];
3041 vert[ 9] = org2[0] + width * right2[0];
3042 vert[10] = org2[1] + width * right2[1];
3043 vert[11] = org2[2] + width * right2[2];
3046 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3048 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)
3053 if (r_refdef.fogenabled)
3054 fog = FogPoint_World(origin);
3056 R_Mesh_Matrix(&identitymatrix);
3057 GL_BlendFunc(blendfunc1, blendfunc2);
3063 GL_CullFace(GL_BACK);
3066 GL_CullFace(GL_FRONT);
3068 GL_DepthMask(false);
3069 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3070 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3071 GL_DepthTest(!depthdisable);
3073 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3074 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3075 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3076 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3077 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3078 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3079 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3080 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3081 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3082 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3083 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3084 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3086 R_Mesh_VertexPointer(vertex3f, 0, 0);
3087 R_Mesh_ColorPointer(NULL, 0, 0);
3088 R_Mesh_ResetTextureState();
3089 R_Mesh_TexBind(0, R_GetTexture(texture));
3090 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3091 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3092 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3093 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3095 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3097 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3098 GL_BlendFunc(blendfunc1, GL_ONE);
3100 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);
3101 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3105 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3110 VectorSet(v, x, y, z);
3111 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3112 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3114 if (i == mesh->numvertices)
3116 if (mesh->numvertices < mesh->maxvertices)
3118 VectorCopy(v, vertex3f);
3119 mesh->numvertices++;
3121 return mesh->numvertices;
3127 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3131 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3132 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3133 e = mesh->element3i + mesh->numtriangles * 3;
3134 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3136 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3137 if (mesh->numtriangles < mesh->maxtriangles)
3142 mesh->numtriangles++;
3144 element[1] = element[2];
3148 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3152 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3153 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3154 e = mesh->element3i + mesh->numtriangles * 3;
3155 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3157 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3158 if (mesh->numtriangles < mesh->maxtriangles)
3163 mesh->numtriangles++;
3165 element[1] = element[2];
3169 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3170 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3172 int planenum, planenum2;
3175 mplane_t *plane, *plane2;
3177 double temppoints[2][256*3];
3178 // figure out how large a bounding box we need to properly compute this brush
3180 for (w = 0;w < numplanes;w++)
3181 maxdist = max(maxdist, planes[w].dist);
3182 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3183 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3184 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3188 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3189 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3191 if (planenum2 == planenum)
3193 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);
3196 if (tempnumpoints < 3)
3198 // generate elements forming a triangle fan for this polygon
3199 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3203 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3206 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3207 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3208 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);
3209 GL_LockArrays(0, brush->numpoints);
3210 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3211 GL_LockArrays(0, 0);
3214 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3217 if (!surface->num_collisiontriangles)
3219 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3220 i = (int)(((size_t)surface) / sizeof(msurface_t));
3221 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);
3222 GL_LockArrays(0, surface->num_collisionvertices);
3223 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3224 GL_LockArrays(0, 0);
3227 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)
3229 texturelayer_t *layer;
3230 layer = t->currentlayers + t->currentnumlayers++;
3232 layer->depthmask = depthmask;
3233 layer->blendfunc1 = blendfunc1;
3234 layer->blendfunc2 = blendfunc2;
3235 layer->texture = texture;
3236 layer->texmatrix = *matrix;
3237 layer->color[0] = r * r_view.colorscale;
3238 layer->color[1] = g * r_view.colorscale;
3239 layer->color[2] = b * r_view.colorscale;
3240 layer->color[3] = a;
3243 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3246 index = parms[2] + r_refdef.time * parms[3];
3247 index -= floor(index);
3251 case Q3WAVEFUNC_NONE:
3252 case Q3WAVEFUNC_NOISE:
3253 case Q3WAVEFUNC_COUNT:
3256 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3257 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3258 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3259 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3260 case Q3WAVEFUNC_TRIANGLE:
3262 f = index - floor(index);
3273 return (float)(parms[0] + parms[1] * f);
3276 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3279 model_t *model = ent->model;
3282 q3shaderinfo_layer_tcmod_t *tcmod;
3284 // switch to an alternate material if this is a q1bsp animated material
3286 texture_t *texture = t;
3287 int s = ent->skinnum;
3288 if ((unsigned int)s >= (unsigned int)model->numskins)
3290 if (model->skinscenes)
3292 if (model->skinscenes[s].framecount > 1)
3293 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3295 s = model->skinscenes[s].firstframe;
3298 t = t + s * model->num_surfaces;
3301 // use an alternate animation if the entity's frame is not 0,
3302 // and only if the texture has an alternate animation
3303 if (ent->frame2 != 0 && t->anim_total[1])
3304 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3306 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3308 texture->currentframe = t;
3311 // update currentskinframe to be a qw skin or animation frame
3312 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3314 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3316 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3317 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3318 r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
3320 t->currentskinframe = r_qwskincache_skinframe[i];
3321 if (t->currentskinframe == NULL)
3322 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3324 else if (t->numskinframes >= 2)
3325 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3326 if (t->backgroundnumskinframes >= 2)
3327 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3329 t->currentmaterialflags = t->basematerialflags;
3330 t->currentalpha = ent->alpha;
3331 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3332 t->currentalpha *= r_wateralpha.value;
3333 if (!(ent->flags & RENDER_LIGHT))
3334 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3335 if (ent->effects & EF_ADDITIVE)
3336 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3337 else if (t->currentalpha < 1)
3338 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3339 if (ent->effects & EF_DOUBLESIDED)
3340 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3341 if (ent->effects & EF_NODEPTHTEST)
3342 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3343 if (ent->flags & RENDER_VIEWMODEL)
3344 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3345 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3346 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3348 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3351 switch(tcmod->tcmod)
3355 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3356 matrix = r_waterscrollmatrix;
3358 matrix = identitymatrix;
3360 case Q3TCMOD_ENTITYTRANSLATE:
3361 // this is used in Q3 to allow the gamecode to control texcoord
3362 // scrolling on the entity, which is not supported in darkplaces yet.
3363 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3365 case Q3TCMOD_ROTATE:
3366 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3367 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3368 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3371 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3373 case Q3TCMOD_SCROLL:
3374 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3376 case Q3TCMOD_STRETCH:
3377 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3378 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3380 case Q3TCMOD_TRANSFORM:
3381 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3382 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3383 VectorSet(tcmat + 6, 0 , 0 , 1);
3384 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3385 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3387 case Q3TCMOD_TURBULENT:
3388 // this is handled in the RSurf_PrepareVertices function
3389 matrix = identitymatrix;
3392 // either replace or concatenate the transformation
3394 t->currenttexmatrix = matrix;
3397 matrix4x4_t temp = t->currenttexmatrix;
3398 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3402 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3403 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3404 t->glosstexture = r_texture_white;
3405 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3406 t->backgroundglosstexture = r_texture_white;
3407 t->specularpower = r_shadow_glossexponent.value;
3408 // TODO: store reference values for these in the texture?
3409 t->specularscale = 0;
3410 if (r_shadow_gloss.integer > 0)
3412 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3414 if (r_shadow_glossintensity.value > 0)
3416 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3417 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3418 t->specularscale = r_shadow_glossintensity.value;
3421 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3422 t->specularscale = r_shadow_gloss2intensity.value;
3425 // lightmaps mode looks bad with dlights using actual texturing, so turn
3426 // off the colormap and glossmap, but leave the normalmap on as it still
3427 // accurately represents the shading involved
3428 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3430 t->basetexture = r_texture_white;
3431 t->specularscale = 0;
3434 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3435 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3436 // submodels are biased to avoid z-fighting with world surfaces that they
3437 // may be exactly overlapping (avoids z-fighting artifacts on certain
3438 // doors and things in Quake maps)
3439 if (ent->model->brush.submodel)
3441 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3442 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3445 VectorClear(t->dlightcolor);
3446 t->currentnumlayers = 0;
3447 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3449 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3451 int blendfunc1, blendfunc2, depthmask;
3452 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3454 blendfunc1 = GL_SRC_ALPHA;
3455 blendfunc2 = GL_ONE;
3457 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3459 blendfunc1 = GL_SRC_ALPHA;
3460 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3462 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3464 blendfunc1 = t->customblendfunc[0];
3465 blendfunc2 = t->customblendfunc[1];
3469 blendfunc1 = GL_ONE;
3470 blendfunc2 = GL_ZERO;
3472 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3473 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3475 rtexture_t *currentbasetexture;
3477 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3478 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3479 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3480 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3482 // fullbright is not affected by r_refdef.lightmapintensity
3483 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3484 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3485 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);
3486 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3487 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);
3492 // set the color tint used for lights affecting this surface
3493 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3495 // q3bsp has no lightmap updates, so the lightstylevalue that
3496 // would normally be baked into the lightmap must be
3497 // applied to the color
3498 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
3499 if (ent->model->type == mod_brushq3)
3500 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3501 colorscale *= r_refdef.lightmapintensity;
3502 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);
3503 if (r_ambient.value >= (1.0f/64.0f))
3504 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);
3505 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3507 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);
3508 if (r_ambient.value >= (1.0f/64.0f))
3509 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);
3511 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3513 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);
3514 if (r_ambient.value >= (1.0f/64.0f))
3515 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);
3518 if (t->currentskinframe->glow != NULL)
3519 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);
3520 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3522 // if this is opaque use alpha blend which will darken the earlier
3525 // if this is an alpha blended material, all the earlier passes
3526 // were darkened by fog already, so we only need to add the fog
3527 // color ontop through the fog mask texture
3529 // if this is an additive blended material, all the earlier passes
3530 // were darkened by fog already, and we should not add fog color
3531 // (because the background was not darkened, there is no fog color
3532 // that was lost behind it).
3533 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);
3540 void R_UpdateAllTextureInfo(entity_render_t *ent)
3544 for (i = 0;i < ent->model->num_texturesperskin;i++)
3545 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3548 rsurfacestate_t rsurface;
3550 void R_Mesh_ResizeArrays(int newvertices)
3553 if (rsurface.array_size >= newvertices)
3555 if (rsurface.array_modelvertex3f)
3556 Mem_Free(rsurface.array_modelvertex3f);
3557 rsurface.array_size = (newvertices + 1023) & ~1023;
3558 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3559 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3560 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3561 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3562 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3563 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3564 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3565 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3566 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3567 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3568 rsurface.array_color4f = base + rsurface.array_size * 27;
3569 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3572 void RSurf_CleanUp(void)
3575 if (rsurface.mode == RSURFMODE_GLSL)
3577 qglUseProgramObjectARB(0);CHECKGLERROR
3579 GL_AlphaTest(false);
3580 rsurface.mode = RSURFMODE_NONE;
3581 rsurface.uselightmaptexture = false;
3582 rsurface.texture = NULL;
3585 void RSurf_ActiveWorldEntity(void)
3587 model_t *model = r_refdef.worldmodel;
3589 if (rsurface.array_size < model->surfmesh.num_vertices)
3590 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3591 rsurface.matrix = identitymatrix;
3592 rsurface.inversematrix = identitymatrix;
3593 R_Mesh_Matrix(&identitymatrix);
3594 VectorCopy(r_view.origin, rsurface.modelorg);
3595 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3596 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3597 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3598 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3599 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3600 rsurface.frameblend[0].frame = 0;
3601 rsurface.frameblend[0].lerp = 1;
3602 rsurface.frameblend[1].frame = 0;
3603 rsurface.frameblend[1].lerp = 0;
3604 rsurface.frameblend[2].frame = 0;
3605 rsurface.frameblend[2].lerp = 0;
3606 rsurface.frameblend[3].frame = 0;
3607 rsurface.frameblend[3].lerp = 0;
3608 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3609 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3610 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3611 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3612 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3613 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3614 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3615 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3616 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3617 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3618 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3619 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3620 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3621 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3622 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3623 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3624 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3625 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3626 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3627 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3628 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3629 rsurface.modelelement3i = model->surfmesh.data_element3i;
3630 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3631 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3632 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3633 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3634 rsurface.modelsurfaces = model->data_surfaces;
3635 rsurface.generatedvertex = false;
3636 rsurface.vertex3f = rsurface.modelvertex3f;
3637 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3638 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3639 rsurface.svector3f = rsurface.modelsvector3f;
3640 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3641 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3642 rsurface.tvector3f = rsurface.modeltvector3f;
3643 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3644 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3645 rsurface.normal3f = rsurface.modelnormal3f;
3646 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3647 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3648 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3651 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3653 model_t *model = ent->model;
3655 if (rsurface.array_size < model->surfmesh.num_vertices)
3656 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3657 rsurface.matrix = ent->matrix;
3658 rsurface.inversematrix = ent->inversematrix;
3659 R_Mesh_Matrix(&rsurface.matrix);
3660 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
3661 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
3662 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
3663 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
3664 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
3665 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
3666 rsurface.frameblend[0] = ent->frameblend[0];
3667 rsurface.frameblend[1] = ent->frameblend[1];
3668 rsurface.frameblend[2] = ent->frameblend[2];
3669 rsurface.frameblend[3] = ent->frameblend[3];
3670 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
3674 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3675 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3676 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3677 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3678 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
3680 else if (wantnormals)
3682 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3683 rsurface.modelsvector3f = NULL;
3684 rsurface.modeltvector3f = NULL;
3685 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3686 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
3690 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
3691 rsurface.modelsvector3f = NULL;
3692 rsurface.modeltvector3f = NULL;
3693 rsurface.modelnormal3f = NULL;
3694 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
3696 rsurface.modelvertex3f_bufferobject = 0;
3697 rsurface.modelvertex3f_bufferoffset = 0;
3698 rsurface.modelsvector3f_bufferobject = 0;
3699 rsurface.modelsvector3f_bufferoffset = 0;
3700 rsurface.modeltvector3f_bufferobject = 0;
3701 rsurface.modeltvector3f_bufferoffset = 0;
3702 rsurface.modelnormal3f_bufferobject = 0;
3703 rsurface.modelnormal3f_bufferoffset = 0;
3704 rsurface.generatedvertex = true;
3708 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3709 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3710 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3711 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3712 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3713 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3714 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3715 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3716 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3717 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3718 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3719 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3720 rsurface.generatedvertex = false;
3722 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3723 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3724 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3725 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3726 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3727 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3728 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3729 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3730 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3731 rsurface.modelelement3i = model->surfmesh.data_element3i;
3732 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3733 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3734 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3735 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3736 rsurface.modelsurfaces = model->data_surfaces;
3737 rsurface.vertex3f = rsurface.modelvertex3f;
3738 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3739 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3740 rsurface.svector3f = rsurface.modelsvector3f;
3741 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3742 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3743 rsurface.tvector3f = rsurface.modeltvector3f;
3744 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3745 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3746 rsurface.normal3f = rsurface.modelnormal3f;
3747 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3748 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3749 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
3752 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
3753 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3756 int texturesurfaceindex;
3761 const float *v1, *in_tc;
3763 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
3765 q3shaderinfo_deform_t *deform;
3766 // 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
3767 if (rsurface.generatedvertex)
3769 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
3770 generatenormals = true;
3771 for (i = 0;i < Q3MAXDEFORMS;i++)
3773 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
3775 generatetangents = true;
3776 generatenormals = true;
3778 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
3779 generatenormals = true;
3781 if (generatenormals && !rsurface.modelnormal3f)
3783 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
3784 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
3785 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
3786 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3788 if (generatetangents && !rsurface.modelsvector3f)
3790 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
3791 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
3792 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
3793 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
3794 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
3795 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
3796 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);
3799 rsurface.vertex3f = rsurface.modelvertex3f;
3800 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3801 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3802 rsurface.svector3f = rsurface.modelsvector3f;
3803 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3804 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3805 rsurface.tvector3f = rsurface.modeltvector3f;
3806 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3807 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3808 rsurface.normal3f = rsurface.modelnormal3f;
3809 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
3810 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
3811 // if vertices are deformed (sprite flares and things in maps, possibly
3812 // water waves, bulges and other deformations), generate them into
3813 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
3814 // (may be static model data or generated data for an animated model, or
3815 // the previous deform pass)
3816 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
3818 switch (deform->deform)
3821 case Q3DEFORM_PROJECTIONSHADOW:
3822 case Q3DEFORM_TEXT0:
3823 case Q3DEFORM_TEXT1:
3824 case Q3DEFORM_TEXT2:
3825 case Q3DEFORM_TEXT3:
3826 case Q3DEFORM_TEXT4:
3827 case Q3DEFORM_TEXT5:
3828 case Q3DEFORM_TEXT6:
3829 case Q3DEFORM_TEXT7:
3832 case Q3DEFORM_AUTOSPRITE:
3833 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3834 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3835 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3836 VectorNormalize(newforward);
3837 VectorNormalize(newright);
3838 VectorNormalize(newup);
3839 // make deformed versions of only the model vertices used by the specified surfaces
3840 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3842 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3843 // a single autosprite surface can contain multiple sprites...
3844 for (j = 0;j < surface->num_vertices - 3;j += 4)
3846 VectorClear(center);
3847 for (i = 0;i < 4;i++)
3848 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3849 VectorScale(center, 0.25f, center);
3850 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
3851 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
3852 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
3853 for (i = 0;i < 4;i++)
3855 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
3856 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3859 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);
3860 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);
3862 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3863 rsurface.vertex3f_bufferobject = 0;
3864 rsurface.vertex3f_bufferoffset = 0;
3865 rsurface.svector3f = rsurface.array_deformedsvector3f;
3866 rsurface.svector3f_bufferobject = 0;
3867 rsurface.svector3f_bufferoffset = 0;
3868 rsurface.tvector3f = rsurface.array_deformedtvector3f;
3869 rsurface.tvector3f_bufferobject = 0;
3870 rsurface.tvector3f_bufferoffset = 0;
3871 rsurface.normal3f = rsurface.array_deformednormal3f;
3872 rsurface.normal3f_bufferobject = 0;
3873 rsurface.normal3f_bufferoffset = 0;
3875 case Q3DEFORM_AUTOSPRITE2:
3876 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
3877 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
3878 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
3879 VectorNormalize(newforward);
3880 VectorNormalize(newright);
3881 VectorNormalize(newup);
3882 // make deformed versions of only the model vertices used by the specified surfaces
3883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3886 const float *v1, *v2;
3896 memset(shortest, 0, sizeof(shortest));
3897 // a single autosprite surface can contain multiple sprites...
3898 for (j = 0;j < surface->num_vertices - 3;j += 4)
3900 VectorClear(center);
3901 for (i = 0;i < 4;i++)
3902 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3903 VectorScale(center, 0.25f, center);
3904 // find the two shortest edges, then use them to define the
3905 // axis vectors for rotating around the central axis
3906 for (i = 0;i < 6;i++)
3908 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
3909 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
3911 Debug_PolygonBegin(NULL, 0, false, 0);
3912 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
3913 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);
3914 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
3917 l = VectorDistance2(v1, v2);
3918 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
3920 l += (1.0f / 1024.0f);
3921 if (shortest[0].length2 > l || i == 0)
3923 shortest[1] = shortest[0];
3924 shortest[0].length2 = l;
3925 shortest[0].v1 = v1;
3926 shortest[0].v2 = v2;
3928 else if (shortest[1].length2 > l || i == 1)
3930 shortest[1].length2 = l;
3931 shortest[1].v1 = v1;
3932 shortest[1].v2 = v2;
3935 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
3936 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
3938 Debug_PolygonBegin(NULL, 0, false, 0);
3939 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
3940 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);
3941 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
3944 // this calculates the right vector from the shortest edge
3945 // and the up vector from the edge midpoints
3946 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
3947 VectorNormalize(right);
3948 VectorSubtract(end, start, up);
3949 VectorNormalize(up);
3950 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
3951 //VectorSubtract(rsurface.modelorg, center, forward);
3952 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
3953 VectorNegate(forward, forward);
3954 VectorReflect(forward, 0, up, forward);
3955 VectorNormalize(forward);
3956 CrossProduct(up, forward, newright);
3957 VectorNormalize(newright);
3959 Debug_PolygonBegin(NULL, 0, false, 0);
3960 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);
3961 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
3962 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3966 Debug_PolygonBegin(NULL, 0, false, 0);
3967 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
3968 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
3969 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
3972 // rotate the quad around the up axis vector, this is made
3973 // especially easy by the fact we know the quad is flat,
3974 // so we only have to subtract the center position and
3975 // measure distance along the right vector, and then
3976 // multiply that by the newright vector and add back the
3978 // we also need to subtract the old position to undo the
3979 // displacement from the center, which we do with a
3980 // DotProduct, the subtraction/addition of center is also
3981 // optimized into DotProducts here
3982 l = DotProduct(right, center);
3983 for (i = 0;i < 4;i++)
3985 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
3986 f = DotProduct(right, v1) - l;
3987 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3990 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);
3991 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);
3993 rsurface.vertex3f = rsurface.array_deformedvertex3f;
3994 rsurface.vertex3f_bufferobject = 0;
3995 rsurface.vertex3f_bufferoffset = 0;
3996 rsurface.svector3f = rsurface.array_deformedsvector3f;
3997 rsurface.svector3f_bufferobject = 0;
3998 rsurface.svector3f_bufferoffset = 0;
3999 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4000 rsurface.tvector3f_bufferobject = 0;
4001 rsurface.tvector3f_bufferoffset = 0;
4002 rsurface.normal3f = rsurface.array_deformednormal3f;
4003 rsurface.normal3f_bufferobject = 0;
4004 rsurface.normal3f_bufferoffset = 0;
4006 case Q3DEFORM_NORMAL:
4007 // deform the normals to make reflections wavey
4008 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4010 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4011 for (j = 0;j < surface->num_vertices;j++)
4014 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4015 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4016 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4017 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4018 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4019 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4020 VectorNormalize(normal);
4022 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);
4024 rsurface.svector3f = rsurface.array_deformedsvector3f;
4025 rsurface.svector3f_bufferobject = 0;
4026 rsurface.svector3f_bufferoffset = 0;
4027 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4028 rsurface.tvector3f_bufferobject = 0;
4029 rsurface.tvector3f_bufferoffset = 0;
4030 rsurface.normal3f = rsurface.array_deformednormal3f;
4031 rsurface.normal3f_bufferobject = 0;
4032 rsurface.normal3f_bufferoffset = 0;
4035 // deform vertex array to make wavey water and flags and such
4036 waveparms[0] = deform->waveparms[0];
4037 waveparms[1] = deform->waveparms[1];
4038 waveparms[2] = deform->waveparms[2];
4039 waveparms[3] = deform->waveparms[3];
4040 // this is how a divisor of vertex influence on deformation
4041 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4042 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4043 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4045 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4046 for (j = 0;j < surface->num_vertices;j++)
4048 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4049 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4050 // if the wavefunc depends on time, evaluate it per-vertex
4053 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4054 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4056 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4059 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4060 rsurface.vertex3f_bufferobject = 0;
4061 rsurface.vertex3f_bufferoffset = 0;
4063 case Q3DEFORM_BULGE:
4064 // deform vertex array to make the surface have moving bulges
4065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4068 for (j = 0;j < surface->num_vertices;j++)
4070 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4071 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4074 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4075 rsurface.vertex3f_bufferobject = 0;
4076 rsurface.vertex3f_bufferoffset = 0;
4079 // deform vertex array
4080 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4081 VectorScale(deform->parms, scale, waveparms);
4082 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4084 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4085 for (j = 0;j < surface->num_vertices;j++)
4086 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4088 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4089 rsurface.vertex3f_bufferobject = 0;
4090 rsurface.vertex3f_bufferoffset = 0;
4094 // generate texcoords based on the chosen texcoord source
4095 switch(rsurface.texture->tcgen.tcgen)
4098 case Q3TCGEN_TEXTURE:
4099 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4100 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4101 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4103 case Q3TCGEN_LIGHTMAP:
4104 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4105 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4106 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4108 case Q3TCGEN_VECTOR:
4109 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4111 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4112 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)
4114 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4115 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4118 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4119 rsurface.texcoordtexture2f_bufferobject = 0;
4120 rsurface.texcoordtexture2f_bufferoffset = 0;
4122 case Q3TCGEN_ENVIRONMENT:
4123 // make environment reflections using a spheremap
4124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4126 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4127 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4128 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4129 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4130 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4132 float l, d, eyedir[3];
4133 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4134 l = 0.5f / VectorLength(eyedir);
4135 d = DotProduct(normal, eyedir)*2;
4136 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4137 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4140 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4141 rsurface.texcoordtexture2f_bufferobject = 0;
4142 rsurface.texcoordtexture2f_bufferoffset = 0;
4145 // the only tcmod that needs software vertex processing is turbulent, so
4146 // check for it here and apply the changes if needed
4147 // and we only support that as the first one
4148 // (handling a mixture of turbulent and other tcmods would be problematic
4149 // without punting it entirely to a software path)
4150 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4152 amplitude = rsurface.texture->tcmods[0].parms[1];
4153 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4154 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4156 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4157 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)
4159 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4160 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4163 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4164 rsurface.texcoordtexture2f_bufferobject = 0;
4165 rsurface.texcoordtexture2f_bufferoffset = 0;
4167 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4168 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4169 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4170 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4173 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4176 const msurface_t *surface = texturesurfacelist[0];
4177 const msurface_t *surface2;
4182 // TODO: lock all array ranges before render, rather than on each surface
4183 if (texturenumsurfaces == 1)
4185 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4186 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));
4188 else if (r_batchmode.integer == 2)
4190 #define MAXBATCHTRIANGLES 4096
4191 int batchtriangles = 0;
4192 int batchelements[MAXBATCHTRIANGLES*3];
4193 for (i = 0;i < texturenumsurfaces;i = j)
4195 surface = texturesurfacelist[i];
4197 if (surface->num_triangles > MAXBATCHTRIANGLES)
4199 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));
4202 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4203 batchtriangles = surface->num_triangles;
4204 firstvertex = surface->num_firstvertex;
4205 endvertex = surface->num_firstvertex + surface->num_vertices;
4206 for (;j < texturenumsurfaces;j++)
4208 surface2 = texturesurfacelist[j];
4209 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4211 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4212 batchtriangles += surface2->num_triangles;
4213 firstvertex = min(firstvertex, surface2->num_firstvertex);
4214 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4216 surface2 = texturesurfacelist[j-1];
4217 numvertices = endvertex - firstvertex;
4218 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4221 else if (r_batchmode.integer == 1)
4223 for (i = 0;i < texturenumsurfaces;i = j)
4225 surface = texturesurfacelist[i];
4226 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4227 if (texturesurfacelist[j] != surface2)
4229 surface2 = texturesurfacelist[j-1];
4230 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4231 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4232 GL_LockArrays(surface->num_firstvertex, numvertices);
4233 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4238 for (i = 0;i < texturenumsurfaces;i++)
4240 surface = texturesurfacelist[i];
4241 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4242 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4247 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4251 const msurface_t *surface = texturesurfacelist[0];
4252 const msurface_t *surface2;
4257 // TODO: lock all array ranges before render, rather than on each surface
4258 if (texturenumsurfaces == 1)
4260 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4261 if (deluxemaptexunit >= 0)
4262 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4263 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4264 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));
4266 else if (r_batchmode.integer == 2)
4268 #define MAXBATCHTRIANGLES 4096
4269 int batchtriangles = 0;
4270 int batchelements[MAXBATCHTRIANGLES*3];
4271 for (i = 0;i < texturenumsurfaces;i = j)
4273 surface = texturesurfacelist[i];
4274 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4275 if (deluxemaptexunit >= 0)
4276 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4278 if (surface->num_triangles > MAXBATCHTRIANGLES)
4280 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));
4283 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4284 batchtriangles = surface->num_triangles;
4285 firstvertex = surface->num_firstvertex;
4286 endvertex = surface->num_firstvertex + surface->num_vertices;
4287 for (;j < texturenumsurfaces;j++)
4289 surface2 = texturesurfacelist[j];
4290 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4292 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4293 batchtriangles += surface2->num_triangles;
4294 firstvertex = min(firstvertex, surface2->num_firstvertex);
4295 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4297 surface2 = texturesurfacelist[j-1];
4298 numvertices = endvertex - firstvertex;
4299 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4302 else if (r_batchmode.integer == 1)
4305 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4306 for (i = 0;i < texturenumsurfaces;i = j)
4308 surface = texturesurfacelist[i];
4309 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4310 if (texturesurfacelist[j] != surface2)
4312 Con_Printf(" %i", j - i);
4315 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4317 for (i = 0;i < texturenumsurfaces;i = j)
4319 surface = texturesurfacelist[i];
4320 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4321 if (deluxemaptexunit >= 0)
4322 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4323 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4324 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4327 Con_Printf(" %i", j - i);
4329 surface2 = texturesurfacelist[j-1];
4330 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4331 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4332 GL_LockArrays(surface->num_firstvertex, numvertices);
4333 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4341 for (i = 0;i < texturenumsurfaces;i++)
4343 surface = texturesurfacelist[i];
4344 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4345 if (deluxemaptexunit >= 0)
4346 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4347 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4348 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));
4353 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4356 int texturesurfaceindex;
4357 if (r_showsurfaces.integer == 2)
4359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4362 for (j = 0;j < surface->num_triangles;j++)
4364 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4365 GL_Color(f, f, f, 1);
4366 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)));
4372 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4374 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4375 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4376 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);
4377 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4378 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));
4383 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4385 int texturesurfaceindex;
4389 if (rsurface.lightmapcolor4f)
4391 // generate color arrays for the surfaces in this list
4392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4394 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4395 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)
4397 f = FogPoint_Model(v);
4407 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4409 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4410 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)
4412 f = FogPoint_Model(v);
4420 rsurface.lightmapcolor4f = rsurface.array_color4f;
4421 rsurface.lightmapcolor4f_bufferobject = 0;
4422 rsurface.lightmapcolor4f_bufferoffset = 0;
4425 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4427 int texturesurfaceindex;
4430 if (!rsurface.lightmapcolor4f)
4432 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4434 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4435 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)
4443 rsurface.lightmapcolor4f = rsurface.array_color4f;
4444 rsurface.lightmapcolor4f_bufferobject = 0;
4445 rsurface.lightmapcolor4f_bufferoffset = 0;
4448 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4451 rsurface.lightmapcolor4f = NULL;
4452 rsurface.lightmapcolor4f_bufferobject = 0;
4453 rsurface.lightmapcolor4f_bufferoffset = 0;
4454 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4455 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4456 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4457 GL_Color(r, g, b, a);
4458 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4461 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4463 // TODO: optimize applyfog && applycolor case
4464 // just apply fog if necessary, and tint the fog color array if necessary
4465 rsurface.lightmapcolor4f = NULL;
4466 rsurface.lightmapcolor4f_bufferobject = 0;
4467 rsurface.lightmapcolor4f_bufferoffset = 0;
4468 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4469 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4470 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4471 GL_Color(r, g, b, a);
4472 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4475 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4477 int texturesurfaceindex;
4481 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4483 // generate color arrays for the surfaces in this list
4484 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4487 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4489 if (surface->lightmapinfo->samples)
4491 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4492 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4493 VectorScale(lm, scale, c);
4494 if (surface->lightmapinfo->styles[1] != 255)
4496 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4498 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4499 VectorMA(c, scale, lm, c);
4500 if (surface->lightmapinfo->styles[2] != 255)
4503 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4504 VectorMA(c, scale, lm, c);
4505 if (surface->lightmapinfo->styles[3] != 255)
4508 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4509 VectorMA(c, scale, lm, c);
4519 rsurface.lightmapcolor4f = rsurface.array_color4f;
4520 rsurface.lightmapcolor4f_bufferobject = 0;
4521 rsurface.lightmapcolor4f_bufferoffset = 0;
4525 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4526 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4527 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4529 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4530 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4531 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4532 GL_Color(r, g, b, a);
4533 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4536 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4538 int texturesurfaceindex;
4542 vec3_t ambientcolor;
4543 vec3_t diffusecolor;
4547 VectorCopy(rsurface.modellight_lightdir, lightdir);
4548 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4549 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4550 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4551 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4552 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4553 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4554 if (VectorLength2(diffusecolor) > 0)
4556 // generate color arrays for the surfaces in this list
4557 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4559 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4560 int numverts = surface->num_vertices;
4561 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4562 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4563 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4564 // q3-style directional shading
4565 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4567 if ((f = DotProduct(c2, lightdir)) > 0)
4568 VectorMA(ambientcolor, f, diffusecolor, c);
4570 VectorCopy(ambientcolor, c);
4579 rsurface.lightmapcolor4f = rsurface.array_color4f;
4580 rsurface.lightmapcolor4f_bufferobject = 0;
4581 rsurface.lightmapcolor4f_bufferoffset = 0;
4585 r = ambientcolor[0];
4586 g = ambientcolor[1];
4587 b = ambientcolor[2];
4588 rsurface.lightmapcolor4f = NULL;
4589 rsurface.lightmapcolor4f_bufferobject = 0;
4590 rsurface.lightmapcolor4f_bufferoffset = 0;
4592 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4593 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4594 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4595 GL_Color(r, g, b, a);
4596 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4599 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4601 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4602 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4603 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4604 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4605 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
4607 rsurface.mode = RSURFMODE_SHOWSURFACES;
4609 GL_BlendFunc(GL_ONE, GL_ZERO);
4610 R_Mesh_ColorPointer(NULL, 0, 0);
4611 R_Mesh_ResetTextureState();
4613 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4614 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4617 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
4619 // transparent sky would be ridiculous
4620 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4622 if (rsurface.mode != RSURFMODE_SKY)
4624 if (rsurface.mode == RSURFMODE_GLSL)
4626 qglUseProgramObjectARB(0);CHECKGLERROR
4628 rsurface.mode = RSURFMODE_SKY;
4632 skyrendernow = false;
4634 // restore entity matrix
4635 R_Mesh_Matrix(&rsurface.matrix);
4637 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4638 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
4639 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4640 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4642 // LordHavoc: HalfLife maps have freaky skypolys so don't use
4643 // skymasking on them, and Quake3 never did sky masking (unlike
4644 // software Quake and software Quake2), so disable the sky masking
4645 // in Quake3 maps as it causes problems with q3map2 sky tricks,
4646 // and skymasking also looks very bad when noclipping outside the
4647 // level, so don't use it then either.
4648 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
4650 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
4651 R_Mesh_ColorPointer(NULL, 0, 0);
4652 R_Mesh_ResetTextureState();
4653 if (skyrendermasked)
4655 // depth-only (masking)
4656 GL_ColorMask(0,0,0,0);
4657 // just to make sure that braindead drivers don't draw
4658 // anything despite that colormask...
4659 GL_BlendFunc(GL_ZERO, GL_ONE);
4664 GL_BlendFunc(GL_ONE, GL_ZERO);
4666 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
4667 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4668 if (skyrendermasked)
4669 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
4673 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
4675 if (rsurface.mode != RSURFMODE_GLSL)
4677 rsurface.mode = RSURFMODE_GLSL;
4678 R_Mesh_ResetTextureState();
4681 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
4682 if (!r_glsl_permutation)
4685 if (rsurface.lightmode == 2)
4686 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4688 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
4689 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4690 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4691 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4692 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4693 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4695 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]);
4696 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4698 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
4699 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4700 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4701 R_Mesh_ColorPointer(NULL, 0, 0);
4703 else if (rsurface.uselightmaptexture)
4705 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
4706 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4707 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
4708 R_Mesh_ColorPointer(NULL, 0, 0);
4712 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
4713 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
4714 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
4715 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4718 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
4719 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
4721 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4722 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4727 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4729 // OpenGL 1.3 path - anything not completely ancient
4730 int texturesurfaceindex;
4731 qboolean applycolor;
4735 const texturelayer_t *layer;
4736 if (rsurface.mode != RSURFMODE_MULTIPASS)
4737 rsurface.mode = RSURFMODE_MULTIPASS;
4738 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4739 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4742 int layertexrgbscale;
4743 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4745 if (layerindex == 0)
4749 GL_AlphaTest(false);
4750 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4753 GL_DepthMask(layer->depthmask);
4754 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4755 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4757 layertexrgbscale = 4;
4758 VectorScale(layer->color, 0.25f, layercolor);
4760 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4762 layertexrgbscale = 2;
4763 VectorScale(layer->color, 0.5f, layercolor);
4767 layertexrgbscale = 1;
4768 VectorScale(layer->color, 1.0f, layercolor);
4770 layercolor[3] = layer->color[3];
4771 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4772 R_Mesh_ColorPointer(NULL, 0, 0);
4773 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4774 switch (layer->type)
4776 case TEXTURELAYERTYPE_LITTEXTURE:
4777 memset(&m, 0, sizeof(m));
4778 m.tex[0] = R_GetTexture(r_texture_white);
4779 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4780 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4781 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4782 m.tex[1] = R_GetTexture(layer->texture);
4783 m.texmatrix[1] = layer->texmatrix;
4784 m.texrgbscale[1] = layertexrgbscale;
4785 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
4786 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
4787 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
4788 R_Mesh_TextureState(&m);
4789 if (rsurface.lightmode == 2)
4790 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4791 else if (rsurface.uselightmaptexture)
4792 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4794 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4796 case TEXTURELAYERTYPE_TEXTURE:
4797 memset(&m, 0, sizeof(m));
4798 m.tex[0] = R_GetTexture(layer->texture);
4799 m.texmatrix[0] = layer->texmatrix;
4800 m.texrgbscale[0] = layertexrgbscale;
4801 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4802 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4803 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4804 R_Mesh_TextureState(&m);
4805 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4807 case TEXTURELAYERTYPE_FOG:
4808 memset(&m, 0, sizeof(m));
4809 m.texrgbscale[0] = layertexrgbscale;
4812 m.tex[0] = R_GetTexture(layer->texture);
4813 m.texmatrix[0] = layer->texmatrix;
4814 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4815 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4816 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4818 R_Mesh_TextureState(&m);
4819 // generate a color array for the fog pass
4820 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4821 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4825 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4826 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)
4828 f = 1 - FogPoint_Model(v);
4829 c[0] = layercolor[0];
4830 c[1] = layercolor[1];
4831 c[2] = layercolor[2];
4832 c[3] = f * layercolor[3];
4835 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4838 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4840 GL_LockArrays(0, 0);
4843 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4845 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4846 GL_AlphaTest(false);
4850 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4852 // OpenGL 1.1 - crusty old voodoo path
4853 int texturesurfaceindex;
4857 const texturelayer_t *layer;
4858 if (rsurface.mode != RSURFMODE_MULTIPASS)
4859 rsurface.mode = RSURFMODE_MULTIPASS;
4860 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4861 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
4863 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4865 if (layerindex == 0)
4869 GL_AlphaTest(false);
4870 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4873 GL_DepthMask(layer->depthmask);
4874 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4875 R_Mesh_ColorPointer(NULL, 0, 0);
4876 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4877 switch (layer->type)
4879 case TEXTURELAYERTYPE_LITTEXTURE:
4880 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4882 // two-pass lit texture with 2x rgbscale
4883 // first the lightmap pass
4884 memset(&m, 0, sizeof(m));
4885 m.tex[0] = R_GetTexture(r_texture_white);
4886 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
4887 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
4888 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
4889 R_Mesh_TextureState(&m);
4890 if (rsurface.lightmode == 2)
4891 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4892 else if (rsurface.uselightmaptexture)
4893 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4895 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4896 GL_LockArrays(0, 0);
4897 // then apply the texture to it
4898 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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 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);
4910 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4911 memset(&m, 0, sizeof(m));
4912 m.tex[0] = R_GetTexture(layer->texture);
4913 m.texmatrix[0] = layer->texmatrix;
4914 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4915 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4916 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4917 R_Mesh_TextureState(&m);
4918 if (rsurface.lightmode == 2)
4919 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);
4921 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);
4924 case TEXTURELAYERTYPE_TEXTURE:
4925 // singletexture unlit texture with transparency support
4926 memset(&m, 0, sizeof(m));
4927 m.tex[0] = R_GetTexture(layer->texture);
4928 m.texmatrix[0] = layer->texmatrix;
4929 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4930 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4931 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4932 R_Mesh_TextureState(&m);
4933 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);
4935 case TEXTURELAYERTYPE_FOG:
4936 // singletexture fogging
4937 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
4940 memset(&m, 0, sizeof(m));
4941 m.tex[0] = R_GetTexture(layer->texture);
4942 m.texmatrix[0] = layer->texmatrix;
4943 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
4944 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
4945 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
4946 R_Mesh_TextureState(&m);
4949 R_Mesh_ResetTextureState();
4950 // generate a color array for the fog pass
4951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4955 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4956 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)
4958 f = 1 - FogPoint_Model(v);
4959 c[0] = layer->color[0];
4960 c[1] = layer->color[1];
4961 c[2] = layer->color[2];
4962 c[3] = f * layer->color[3];
4965 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4968 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4970 GL_LockArrays(0, 0);
4973 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4975 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4976 GL_AlphaTest(false);
4980 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
4982 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4984 rsurface.rtlight = NULL;
4988 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
4990 if (rsurface.mode != RSURFMODE_MULTIPASS)
4991 rsurface.mode = RSURFMODE_MULTIPASS;
4992 if (r_depthfirst.integer == 3)
4994 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
4995 if (!r_view.showdebug)
4996 GL_Color(0, 0, 0, 1);
4998 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5002 GL_ColorMask(0,0,0,0);
5005 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5006 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5007 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5009 GL_BlendFunc(GL_ONE, GL_ZERO);
5011 GL_AlphaTest(false);
5012 R_Mesh_ColorPointer(NULL, 0, 0);
5013 R_Mesh_ResetTextureState();
5014 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5015 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5016 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5017 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5019 else if (r_depthfirst.integer == 3)
5021 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5023 GL_Color(0, 0, 0, 1);
5024 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5026 else if (r_showsurfaces.integer)
5028 if (rsurface.mode != RSURFMODE_MULTIPASS)
5029 rsurface.mode = RSURFMODE_MULTIPASS;
5030 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5031 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5033 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5034 GL_BlendFunc(GL_ONE, GL_ZERO);
5035 GL_DepthMask(writedepth);
5037 GL_AlphaTest(false);
5038 R_Mesh_ColorPointer(NULL, 0, 0);
5039 R_Mesh_ResetTextureState();
5040 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5041 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5042 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5044 else if (gl_lightmaps.integer)
5047 if (rsurface.mode != RSURFMODE_MULTIPASS)
5048 rsurface.mode = RSURFMODE_MULTIPASS;
5049 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5051 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5052 GL_BlendFunc(GL_ONE, GL_ZERO);
5053 GL_DepthMask(writedepth);
5055 GL_AlphaTest(false);
5056 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5057 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5058 R_Mesh_ColorPointer(NULL, 0, 0);
5059 memset(&m, 0, sizeof(m));
5060 m.tex[0] = R_GetTexture(r_texture_white);
5061 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5062 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5063 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5064 R_Mesh_TextureState(&m);
5065 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5066 if (rsurface.lightmode == 2)
5067 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5068 else if (rsurface.uselightmaptexture)
5069 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5071 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5072 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5074 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5076 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5077 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5079 else if (rsurface.texture->currentnumlayers)
5081 // write depth for anything we skipped on the depth-only pass earlier
5082 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5084 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5085 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5086 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5087 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
5088 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5089 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5090 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5091 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5092 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5093 if (r_glsl.integer && gl_support_fragment_shader)
5094 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5095 else if (gl_combine.integer && r_textureunits.integer >= 2)
5096 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5098 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5099 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5102 GL_LockArrays(0, 0);
5105 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5108 int texturenumsurfaces, endsurface;
5110 msurface_t *surface;
5111 msurface_t *texturesurfacelist[1024];
5113 // if the model is static it doesn't matter what value we give for
5114 // wantnormals and wanttangents, so this logic uses only rules applicable
5115 // to a model, knowing that they are meaningless otherwise
5116 if (ent == r_refdef.worldentity)
5117 RSurf_ActiveWorldEntity();
5118 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5119 RSurf_ActiveModelEntity(ent, false, false);
5121 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5123 for (i = 0;i < numsurfaces;i = j)
5126 surface = rsurface.modelsurfaces + surfacelist[i];
5127 texture = surface->texture;
5128 R_UpdateTextureInfo(ent, texture);
5129 rsurface.texture = texture->currentframe;
5130 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5131 // scan ahead until we find a different texture
5132 endsurface = min(i + 1024, numsurfaces);
5133 texturenumsurfaces = 0;
5134 texturesurfacelist[texturenumsurfaces++] = surface;
5135 for (;j < endsurface;j++)
5137 surface = rsurface.modelsurfaces + surfacelist[j];
5138 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5140 texturesurfacelist[texturenumsurfaces++] = surface;
5142 // render the range of surfaces
5143 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5149 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
5152 vec3_t tempcenter, center;
5154 // break the surface list down into batches by texture and use of lightmapping
5155 for (i = 0;i < numsurfaces;i = j)
5158 // texture is the base texture pointer, rsurface.texture is the
5159 // current frame/skin the texture is directing us to use (for example
5160 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5161 // use skin 1 instead)
5162 texture = surfacelist[i]->texture;
5163 rsurface.texture = texture->currentframe;
5164 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5165 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5167 // if this texture is not the kind we want, skip ahead to the next one
5168 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5172 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5174 // transparent surfaces get pushed off into the transparent queue
5175 const msurface_t *surface = surfacelist[i];
5178 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5179 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5180 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5181 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5182 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5186 // simply scan ahead until we find a different texture or lightmap state
5187 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5189 // render the range of surfaces
5190 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5195 float locboxvertex3f[6*4*3] =
5197 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5198 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5199 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5200 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5201 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5202 1,0,0, 0,0,0, 0,1,0, 1,1,0
5205 int locboxelement3i[6*2*3] =
5215 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5218 cl_locnode_t *loc = (cl_locnode_t *)ent;
5220 float vertex3f[6*4*3];
5222 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5223 GL_DepthMask(false);
5224 GL_DepthRange(0, 1);
5225 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5227 GL_CullFace(GL_NONE);
5228 R_Mesh_Matrix(&identitymatrix);
5230 R_Mesh_VertexPointer(vertex3f, 0, 0);
5231 R_Mesh_ColorPointer(NULL, 0, 0);
5232 R_Mesh_ResetTextureState();
5235 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5236 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5237 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5238 surfacelist[0] < 0 ? 0.5f : 0.125f);
5240 if (VectorCompare(loc->mins, loc->maxs))
5242 VectorSet(size, 2, 2, 2);
5243 VectorMA(loc->mins, -0.5f, size, mins);
5247 VectorCopy(loc->mins, mins);
5248 VectorSubtract(loc->maxs, loc->mins, size);
5251 for (i = 0;i < 6*4*3;)
5252 for (j = 0;j < 3;j++, i++)
5253 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5255 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5258 void R_DrawLocs(void)
5261 cl_locnode_t *loc, *nearestloc;
5263 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5264 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5266 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5267 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5271 void R_DrawCollisionBrushes(entity_render_t *ent)
5275 msurface_t *surface;
5276 model_t *model = ent->model;
5277 if (!model->brush.num_brushes)
5280 R_Mesh_ColorPointer(NULL, 0, 0);
5281 R_Mesh_ResetTextureState();
5282 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5283 GL_DepthMask(false);
5284 GL_DepthRange(0, 1);
5285 GL_DepthTest(!r_showdisabledepthtest.integer);
5286 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5287 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5288 if (brush->colbrushf && brush->colbrushf->numtriangles)
5289 R_DrawCollisionBrush(brush->colbrushf);
5290 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5291 if (surface->num_collisiontriangles)
5292 R_DrawCollisionSurface(ent, surface);
5293 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5296 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5299 const int *elements;
5300 msurface_t *surface;
5301 model_t *model = ent->model;
5304 GL_DepthRange(0, 1);
5305 GL_DepthTest(!r_showdisabledepthtest.integer);
5306 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5308 GL_BlendFunc(GL_ONE, GL_ZERO);
5309 R_Mesh_ColorPointer(NULL, 0, 0);
5310 R_Mesh_ResetTextureState();
5311 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5313 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5315 rsurface.texture = surface->texture->currentframe;
5316 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5318 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5321 if (!rsurface.texture->currentlayers->depthmask)
5322 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5323 else if (ent == r_refdef.worldentity)
5324 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5326 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5327 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5330 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5332 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5333 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5334 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5335 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5342 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5344 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5346 VectorCopy(rsurface.vertex3f + l * 3, v);
5347 qglVertex3f(v[0], v[1], v[2]);
5348 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5349 qglVertex3f(v[0], v[1], v[2]);
5353 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5355 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5357 VectorCopy(rsurface.vertex3f + l * 3, v);
5358 qglVertex3f(v[0], v[1], v[2]);
5359 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5360 qglVertex3f(v[0], v[1], v[2]);
5364 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5366 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5368 VectorCopy(rsurface.vertex3f + l * 3, v);
5369 qglVertex3f(v[0], v[1], v[2]);
5370 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5371 qglVertex3f(v[0], v[1], v[2]);
5378 rsurface.texture = NULL;
5381 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5382 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5384 int i, j, endj, f, flagsmask;
5385 int counttriangles = 0;
5386 msurface_t *surface, **surfacechain;
5388 model_t *model = r_refdef.worldmodel;
5389 const int maxsurfacelist = 1024;
5390 int numsurfacelist = 0;
5391 msurface_t *surfacelist[1024];
5395 RSurf_ActiveWorldEntity();
5397 // update light styles
5398 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5400 for (i = 0;i < model->brushq1.light_styles;i++)
5402 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5404 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5405 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5406 for (;(surface = *surfacechain);surfacechain++)
5407 surface->cached_dlight = true;
5412 R_UpdateAllTextureInfo(r_refdef.worldentity);
5413 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5416 rsurface.uselightmaptexture = false;
5417 rsurface.texture = NULL;
5419 j = model->firstmodelsurface;
5420 endj = j + model->nummodelsurfaces;
5423 // quickly skip over non-visible surfaces
5424 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5426 // quickly iterate over visible surfaces
5427 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5429 // process this surface
5430 surface = model->data_surfaces + j;
5431 // if this surface fits the criteria, add it to the list
5432 if (surface->num_triangles)
5434 // if lightmap parameters changed, rebuild lightmap texture
5435 if (surface->cached_dlight)
5436 R_BuildLightMap(r_refdef.worldentity, surface);
5437 // add face to draw list
5438 surfacelist[numsurfacelist++] = surface;
5439 counttriangles += surface->num_triangles;
5440 if (numsurfacelist >= maxsurfacelist)
5442 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5449 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5450 r_refdef.stats.entities_triangles += counttriangles;
5453 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5454 R_DrawCollisionBrushes(r_refdef.worldentity);
5456 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5457 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5460 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly)
5462 int i, f, flagsmask;
5463 int counttriangles = 0;
5464 msurface_t *surface, *endsurface, **surfacechain;
5466 model_t *model = ent->model;
5467 const int maxsurfacelist = 1024;
5468 int numsurfacelist = 0;
5469 msurface_t *surfacelist[1024];
5473 // if the model is static it doesn't matter what value we give for
5474 // wantnormals and wanttangents, so this logic uses only rules applicable
5475 // to a model, knowing that they are meaningless otherwise
5476 if (ent == r_refdef.worldentity)
5477 RSurf_ActiveWorldEntity();
5478 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5479 RSurf_ActiveModelEntity(ent, false, false);
5481 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5483 // update light styles
5484 if (!skysurfaces && !depthonly && model->brushq1.light_styleupdatechains)
5486 for (i = 0;i < model->brushq1.light_styles;i++)
5488 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5490 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5491 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5492 for (;(surface = *surfacechain);surfacechain++)
5493 surface->cached_dlight = true;
5498 R_UpdateAllTextureInfo(ent);
5499 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
5502 rsurface.uselightmaptexture = false;
5503 rsurface.texture = NULL;
5505 surface = model->data_surfaces + model->firstmodelsurface;
5506 endsurface = surface + model->nummodelsurfaces;
5507 for (;surface < endsurface;surface++)
5509 // if this surface fits the criteria, add it to the list
5510 if (surface->num_triangles)
5512 // if lightmap parameters changed, rebuild lightmap texture
5513 if (surface->cached_dlight)
5514 R_BuildLightMap(ent, surface);
5515 // add face to draw list
5516 surfacelist[numsurfacelist++] = surface;
5517 counttriangles += surface->num_triangles;
5518 if (numsurfacelist >= maxsurfacelist)
5520 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5526 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly);
5527 r_refdef.stats.entities_triangles += counttriangles;
5530 if (r_view.showdebug)
5532 if (r_showcollisionbrushes.integer && !skysurfaces && !depthonly)
5533 R_DrawCollisionBrushes(ent);
5535 if ((r_showtris.integer || r_shownormals.integer) && !depthonly)
5536 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);