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_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
85 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
86 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
87 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
88 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
90 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
91 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
92 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
94 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
95 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
96 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
97 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
98 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
99 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
100 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
102 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
103 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
104 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
105 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)"};
107 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"};
109 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"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
114 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
116 extern qboolean v_flipped_state;
118 typedef struct r_glsl_bloomshader_s
121 int loc_Texture_Bloom;
123 r_glsl_bloomshader_t;
125 static struct r_bloomstate_s
130 int bloomwidth, bloomheight;
132 int screentexturewidth, screentextureheight;
133 rtexture_t *texture_screen;
135 int bloomtexturewidth, bloomtextureheight;
136 rtexture_t *texture_bloom;
138 r_glsl_bloomshader_t *shader;
140 // arrays for rendering the screen passes
141 float screentexcoord2f[8];
142 float bloomtexcoord2f[8];
143 float offsettexcoord2f[8];
147 typedef struct r_waterstate_waterplane_s
149 rtexture_t *texture_refraction;
150 rtexture_t *texture_reflection;
152 int materialflags; // combined flags of all water surfaces on this plane
153 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
156 r_waterstate_waterplane_t;
158 #define MAX_WATERPLANES 16
160 static struct r_waterstate_s
164 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
166 int waterwidth, waterheight;
167 int texturewidth, textureheight;
169 int maxwaterplanes; // same as MAX_WATERPLANES
171 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
173 float screenscale[2];
174 float screencenter[2];
178 // shadow volume bsp struct with automatically growing nodes buffer
181 rtexture_t *r_texture_blanknormalmap;
182 rtexture_t *r_texture_white;
183 rtexture_t *r_texture_grey128;
184 rtexture_t *r_texture_black;
185 rtexture_t *r_texture_notexture;
186 rtexture_t *r_texture_whitecube;
187 rtexture_t *r_texture_normalizationcube;
188 rtexture_t *r_texture_fogattenuation;
189 //rtexture_t *r_texture_fogintensity;
191 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
192 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
194 // vertex coordinates for a quad that covers the screen exactly
195 const static float r_screenvertex3f[12] =
203 extern void R_DrawModelShadows(void);
205 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
208 for (i = 0;i < verts;i++)
219 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
222 for (i = 0;i < verts;i++)
232 // FIXME: move this to client?
235 if (gamemode == GAME_NEHAHRA)
237 Cvar_Set("gl_fogenable", "0");
238 Cvar_Set("gl_fogdensity", "0.2");
239 Cvar_Set("gl_fogred", "0.3");
240 Cvar_Set("gl_foggreen", "0.3");
241 Cvar_Set("gl_fogblue", "0.3");
243 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
246 float FogPoint_World(const vec3_t p)
248 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
249 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
252 float FogPoint_Model(const vec3_t p)
254 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
255 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
258 static void R_BuildBlankTextures(void)
260 unsigned char data[4];
261 data[0] = 128; // normal X
262 data[1] = 128; // normal Y
263 data[2] = 255; // normal Z
264 data[3] = 128; // height
265 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
270 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
387 unsigned char data1[FOGWIDTH][4];
388 //unsigned char data2[FOGWIDTH][4];
389 for (x = 0;x < FOGWIDTH;x++)
391 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
396 //data2[x][0] = 255 - b;
397 //data2[x][1] = 255 - b;
398 //data2[x][2] = 255 - b;
401 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
402 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
405 static const char *builtinshaderstring =
406 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
407 "// written by Forest 'LordHavoc' Hale\n"
409 "// common definitions between vertex shader and fragment shader:\n"
411 "#ifdef __GLSL_CG_DATA_TYPES\n"
412 "# define myhalf half\n"
413 "# define myhvec2 hvec2\n"
414 "# define myhvec3 hvec3\n"
415 "# define myhvec4 hvec4\n"
417 "# define myhalf float\n"
418 "# define myhvec2 vec2\n"
419 "# define myhvec3 vec3\n"
420 "# define myhvec4 vec4\n"
423 "varying vec2 TexCoord;\n"
424 "varying vec2 TexCoordLightmap;\n"
426 "//#ifdef MODE_LIGHTSOURCE\n"
427 "varying vec3 CubeVector;\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 LightVector;\n"
433 "//# ifdef MODE_LIGHTDIRECTION\n"
434 "//varying vec3 LightVector;\n"
438 "varying vec3 EyeVector;\n"
440 "varying vec3 EyeVectorModelSpace;\n"
443 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
444 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
445 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
447 "//#ifdef MODE_WATER\n"
448 "varying vec4 ModelViewProjectionPosition;\n"
450 "//# ifdef MODE_REFRACTION\n"
451 "//varying vec4 ModelViewProjectionPosition;\n"
453 "//# ifdef USEREFLECTION\n"
454 "//varying vec4 ModelViewProjectionPosition;\n"
463 "// vertex shader specific:\n"
464 "#ifdef VERTEX_SHADER\n"
466 "uniform vec3 LightPosition;\n"
467 "uniform vec3 EyePosition;\n"
468 "uniform vec3 LightDir;\n"
470 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
474 " gl_FrontColor = gl_Color;\n"
475 " // copy the surface texcoord\n"
476 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#ifndef MODE_LIGHTSOURCE\n"
478 "# ifndef MODE_LIGHTDIRECTION\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 EyeVectorModelSpace;\n"
507 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
508 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
509 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
510 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
512 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
513 " VectorS = gl_MultiTexCoord1.xyz;\n"
514 " VectorT = gl_MultiTexCoord2.xyz;\n"
515 " VectorR = gl_MultiTexCoord3.xyz;\n"
518 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
519 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
520 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
521 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
524 "// transform vertex to camera space, using ftransform to match non-VS\n"
526 " gl_Position = ftransform();\n"
528 "#ifdef MODE_WATER\n"
529 " ModelViewProjectionPosition = gl_Position;\n"
531 "#ifdef MODE_REFRACTION\n"
532 " ModelViewProjectionPosition = gl_Position;\n"
534 "#ifdef USEREFLECTION\n"
535 " ModelViewProjectionPosition = gl_Position;\n"
539 "#endif // VERTEX_SHADER\n"
544 "// fragment shader specific:\n"
545 "#ifdef FRAGMENT_SHADER\n"
547 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
548 "uniform sampler2D Texture_Normal;\n"
549 "uniform sampler2D Texture_Color;\n"
550 "uniform sampler2D Texture_Gloss;\n"
551 "uniform samplerCube Texture_Cube;\n"
552 "uniform sampler2D Texture_Attenuation;\n"
553 "uniform sampler2D Texture_FogMask;\n"
554 "uniform sampler2D Texture_Pants;\n"
555 "uniform sampler2D Texture_Shirt;\n"
556 "uniform sampler2D Texture_Lightmap;\n"
557 "uniform sampler2D Texture_Deluxemap;\n"
558 "uniform sampler2D Texture_Glow;\n"
559 "uniform sampler2D Texture_Reflection;\n"
560 "uniform sampler2D Texture_Refraction;\n"
562 "uniform myhvec3 LightColor;\n"
563 "uniform myhvec3 AmbientColor;\n"
564 "uniform myhvec3 DiffuseColor;\n"
565 "uniform myhvec3 SpecularColor;\n"
566 "uniform myhvec3 Color_Pants;\n"
567 "uniform myhvec3 Color_Shirt;\n"
568 "uniform myhvec3 FogColor;\n"
570 "//#ifdef MODE_WATER\n"
571 "uniform vec4 DistortScaleRefractReflect;\n"
572 "uniform vec4 ScreenScaleRefractReflect;\n"
573 "uniform vec4 ScreenCenterRefractReflect;\n"
574 "uniform myhvec4 RefractColor;\n"
575 "uniform myhvec4 ReflectColor;\n"
576 "uniform myhalf ReflectFactor;\n"
577 "uniform myhalf ReflectOffset;\n"
579 "//# ifdef MODE_REFRACTION\n"
580 "//uniform vec4 DistortScaleRefractReflect;\n"
581 "//uniform vec4 ScreenScaleRefractReflect;\n"
582 "//uniform vec4 ScreenCenterRefractReflect;\n"
583 "//uniform myhvec4 RefractColor;\n"
584 "//# ifdef USEREFLECTION\n"
585 "//uniform myhvec4 ReflectColor;\n"
588 "//# ifdef USEREFLECTION\n"
589 "//uniform vec4 DistortScaleRefractReflect;\n"
590 "//uniform vec4 ScreenScaleRefractReflect;\n"
591 "//uniform vec4 ScreenCenterRefractReflect;\n"
592 "//uniform myhvec4 ReflectColor;\n"
597 "uniform myhalf GlowScale;\n"
598 "uniform myhalf SceneBrightness;\n"
599 "#ifdef USECONTRASTBOOST\n"
600 "uniform myhalf ContrastBoostCoeff;\n"
603 "uniform float OffsetMapping_Scale;\n"
604 "uniform float OffsetMapping_Bias;\n"
605 "uniform float FogRangeRecip;\n"
607 "uniform myhalf AmbientScale;\n"
608 "uniform myhalf DiffuseScale;\n"
609 "uniform myhalf SpecularScale;\n"
610 "uniform myhalf SpecularPower;\n"
612 "#ifdef USEOFFSETMAPPING\n"
613 "vec2 OffsetMapping(vec2 TexCoord)\n"
615 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
616 " // 14 sample relief mapping: linear search and then binary search\n"
617 " // this basically steps forward a small amount repeatedly until it finds\n"
618 " // itself inside solid, then jitters forward and back using decreasing\n"
619 " // amounts to find the impact\n"
620 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
621 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
622 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
623 " vec3 RT = vec3(TexCoord, 1);\n"
624 " OffsetVector *= 0.1;\n"
625 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
626 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
627 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
628 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
629 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
630 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
631 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
632 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
633 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
634 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
635 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
636 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
637 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
638 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
641 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
642 " // this basically moves forward the full distance, and then backs up based\n"
643 " // on height of samples\n"
644 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
645 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
646 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
647 " TexCoord += OffsetVector;\n"
648 " OffsetVector *= 0.333;\n"
649 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
650 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
651 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
652 " return TexCoord;\n"
655 "#endif // USEOFFSETMAPPING\n"
657 "#ifdef MODE_WATER\n"
662 "#ifdef USEOFFSETMAPPING\n"
663 " // apply offsetmapping\n"
664 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
665 "#define TexCoord TexCoordOffset\n"
668 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
669 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
670 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
671 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
672 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
675 "#else // MODE_WATER\n"
676 "#ifdef MODE_REFRACTION\n"
678 "// refraction pass\n"
681 "#ifdef USEOFFSETMAPPING\n"
682 " // apply offsetmapping\n"
683 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
684 "#define TexCoord TexCoordOffset\n"
687 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
688 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
689 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
690 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
693 "#else // MODE_REFRACTION\n"
696 "#ifdef USEOFFSETMAPPING\n"
697 " // apply offsetmapping\n"
698 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
699 "#define TexCoord TexCoordOffset\n"
702 " // combine the diffuse textures (base, pants, shirt)\n"
703 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
704 "#ifdef USECOLORMAPPING\n"
705 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
711 "#ifdef MODE_LIGHTSOURCE\n"
714 " // calculate surface normal, light normal, and specular normal\n"
715 " // compute color intensity for the two textures (colormap and glossmap)\n"
716 " // scale by light color and attenuation as efficiently as possible\n"
717 " // (do as much scalar math as possible rather than vector math)\n"
718 "# ifdef USESPECULAR\n"
719 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
720 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
721 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
723 " // calculate directional shading\n"
724 " 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"
726 "# ifdef USEDIFFUSE\n"
727 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
728 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
730 " // calculate directional shading\n"
731 " 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"
733 " // calculate directionless shading\n"
734 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
738 "# ifdef USECUBEFILTER\n"
739 " // apply light cubemap filter\n"
740 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
741 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
743 " color *= myhvec4(gl_Color);\n"
744 "#endif // MODE_LIGHTSOURCE\n"
749 "#ifdef MODE_LIGHTDIRECTION\n"
750 " // directional model lighting\n"
752 " // get the surface normal and light normal\n"
753 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
754 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
756 " // calculate directional shading\n"
757 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
758 "# ifdef USESPECULAR\n"
759 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
760 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
762 " color *= myhvec4(gl_Color);\n"
763 "#endif // MODE_LIGHTDIRECTION\n"
768 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
769 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
771 " // get the surface normal and light normal\n"
772 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
774 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
775 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
776 " // calculate directional shading\n"
777 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
778 "# ifdef USESPECULAR\n"
779 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
780 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
783 " // apply lightmap color\n"
784 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
785 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
790 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
791 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
793 " // get the surface normal and light normal\n"
794 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
796 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
797 " // calculate directional shading\n"
798 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
799 "# ifdef USESPECULAR\n"
800 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
801 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
804 " // apply lightmap color\n"
805 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
806 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
811 "#ifdef MODE_LIGHTMAP\n"
812 " // apply lightmap color\n"
813 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
814 "#endif // MODE_LIGHTMAP\n"
824 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
827 "#ifdef USECONTRASTBOOST\n"
828 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
831 " color.rgb *= SceneBrightness;\n"
833 "#ifndef MODE_LIGHTSOURCE\n"
834 "# ifdef USEREFLECTION\n"
835 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
836 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
837 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
838 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
844 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
847 " gl_FragColor = vec4(color);\n"
849 "#endif // MODE_REFRACTION\n"
850 "#endif // MODE_WATER\n"
852 "#endif // FRAGMENT_SHADER\n"
855 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
856 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
857 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
858 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
859 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
860 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
861 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
862 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
863 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
864 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
865 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
867 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
868 const char *shaderpermutationinfo[][2] =
870 {"#define USECOLORMAPPING\n", " colormapping"},
871 {"#define USECONTRASTBOOST\n", " contrastboost"},
872 {"#define USEFOG\n", " fog"},
873 {"#define USECUBEFILTER\n", " cubefilter"},
874 {"#define USEGLOW\n", " glow"},
875 {"#define USEDIFFUSE\n", " diffuse"},
876 {"#define USESPECULAR\n", " specular"},
877 {"#define USEREFLECTION\n", " reflection"},
878 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
879 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
883 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
884 typedef enum shadermode_e
886 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
887 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
888 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
889 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
890 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
891 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
892 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
897 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
898 const char *shadermodeinfo[][2] =
900 {"#define MODE_LIGHTMAP\n", " lightmap"},
901 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
902 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
903 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
904 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
905 {"#define MODE_REFRACTION\n", " refraction"},
906 {"#define MODE_WATER\n", " water"},
910 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
912 typedef struct r_glsl_permutation_s
914 // indicates if we have tried compiling this permutation already
916 // 0 if compilation failed
918 // locations of detected uniforms in program object, or -1 if not found
919 int loc_Texture_Normal;
920 int loc_Texture_Color;
921 int loc_Texture_Gloss;
922 int loc_Texture_Cube;
923 int loc_Texture_Attenuation;
924 int loc_Texture_FogMask;
925 int loc_Texture_Pants;
926 int loc_Texture_Shirt;
927 int loc_Texture_Lightmap;
928 int loc_Texture_Deluxemap;
929 int loc_Texture_Glow;
930 int loc_Texture_Refraction;
931 int loc_Texture_Reflection;
933 int loc_LightPosition;
938 int loc_FogRangeRecip;
939 int loc_AmbientScale;
940 int loc_DiffuseScale;
941 int loc_SpecularScale;
942 int loc_SpecularPower;
944 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
945 int loc_OffsetMapping_Scale;
946 int loc_AmbientColor;
947 int loc_DiffuseColor;
948 int loc_SpecularColor;
950 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
951 int loc_DistortScaleRefractReflect;
952 int loc_ScreenScaleRefractReflect;
953 int loc_ScreenCenterRefractReflect;
954 int loc_RefractColor;
955 int loc_ReflectColor;
956 int loc_ReflectFactor;
957 int loc_ReflectOffset;
959 r_glsl_permutation_t;
961 // information about each possible shader permutation
962 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
963 // currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
966 // these are additional flags used only by R_GLSL_CompilePermutation
967 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
968 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
969 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
971 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
974 qboolean shaderfound;
975 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
976 int vertstrings_count;
977 int geomstrings_count;
978 int fragstrings_count;
980 const char *vertstrings_list[32+1];
981 const char *geomstrings_list[32+1];
982 const char *fragstrings_list[32+1];
983 char permutationname[256];
988 vertstrings_list[0] = "#define VERTEX_SHADER\n";
989 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
990 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
991 vertstrings_count = 1;
992 geomstrings_count = 1;
993 fragstrings_count = 1;
994 permutationname[0] = 0;
995 i = permutation / SHADERPERMUTATION_MODEBASE;
996 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
997 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
998 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
999 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1000 for (i = 0;shaderpermutationinfo[i][0];i++)
1002 if (permutation & (1<<i))
1004 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1005 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1006 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1007 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1011 // keep line numbers correct
1012 vertstrings_list[vertstrings_count++] = "\n";
1013 geomstrings_list[geomstrings_count++] = "\n";
1014 fragstrings_list[fragstrings_count++] = "\n";
1017 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1018 shaderfound = false;
1021 Con_DPrint("from disk... ");
1022 vertstrings_list[vertstrings_count++] = shaderstring;
1023 geomstrings_list[geomstrings_count++] = shaderstring;
1024 fragstrings_list[fragstrings_count++] = shaderstring;
1027 else if (!strcmp(filename, "glsl/default.glsl"))
1029 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1030 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1031 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1034 // clear any lists that are not needed by this shader
1035 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1036 vertstrings_count = 0;
1037 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1038 geomstrings_count = 0;
1039 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1040 fragstrings_count = 0;
1041 // compile the shader program
1042 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1043 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1047 qglUseProgramObjectARB(p->program);CHECKGLERROR
1048 // look up all the uniform variable names we care about, so we don't
1049 // have to look them up every time we set them
1050 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1051 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1052 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1053 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1054 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1055 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1056 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1057 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1058 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1059 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1060 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1061 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1062 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1063 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1064 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1065 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1066 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1067 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1068 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1069 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1070 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1071 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1072 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1073 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1074 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1075 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1076 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1077 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1078 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1079 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1080 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1081 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1082 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1083 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1084 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1085 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1086 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1087 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1088 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1089 // initialize the samplers to refer to the texture units we use
1090 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1091 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1092 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1093 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1094 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1095 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1096 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1097 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1098 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1099 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1100 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1101 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1102 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1104 qglUseProgramObjectARB(0);CHECKGLERROR
1105 if (developer.integer)
1106 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1110 if (developer.integer)
1111 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1113 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1116 Mem_Free(shaderstring);
1119 void R_GLSL_Restart_f(void)
1122 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1123 if (r_glsl_permutations[i].program)
1124 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1125 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1128 void R_GLSL_DumpShader_f(void)
1132 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1135 Con_Printf("failed to write to glsl/default.glsl\n");
1139 FS_Print(file, "// The engine may define the following macros:\n");
1140 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1141 for (i = 0;shadermodeinfo[i][0];i++)
1142 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1143 for (i = 0;shaderpermutationinfo[i][0];i++)
1144 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1145 FS_Print(file, "\n");
1146 FS_Print(file, builtinshaderstring);
1149 Con_Printf("glsl/default.glsl written\n");
1152 extern rtexture_t *r_shadow_attenuationgradienttexture;
1153 extern rtexture_t *r_shadow_attenuation2dtexture;
1154 extern rtexture_t *r_shadow_attenuation3dtexture;
1155 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1157 // select a permutation of the lighting shader appropriate to this
1158 // combination of texture, entity, light source, and fogging, only use the
1159 // minimum features necessary to avoid wasting rendering time in the
1160 // fragment shader on features that are not being used
1161 const char *shaderfilename = NULL;
1162 unsigned int permutation = 0;
1163 unsigned int shadertype = 0;
1164 shadermode_t mode = 0;
1165 r_glsl_permutation = NULL;
1166 shaderfilename = "glsl/default.glsl";
1167 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1168 // TODO: implement geometry-shader based shadow volumes someday
1169 if (r_glsl_offsetmapping.integer)
1171 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1172 if (r_glsl_offsetmapping_reliefmapping.integer)
1173 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1175 if (rsurfacepass == RSURFPASS_BACKGROUND)
1177 // distorted background
1178 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1179 mode = SHADERMODE_WATER;
1181 mode = SHADERMODE_REFRACTION;
1183 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1186 mode = SHADERMODE_LIGHTSOURCE;
1187 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1188 permutation |= SHADERPERMUTATION_CUBEFILTER;
1189 if (diffusescale > 0)
1190 permutation |= SHADERPERMUTATION_DIFFUSE;
1191 if (specularscale > 0)
1192 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1193 if (r_refdef.fogenabled)
1194 permutation |= SHADERPERMUTATION_FOG;
1195 if (rsurface.texture->colormapping)
1196 permutation |= SHADERPERMUTATION_COLORMAPPING;
1197 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1198 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1200 permutation |= SHADERPERMUTATION_REFLECTION;
1202 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1204 // bright unshaded geometry
1205 mode = SHADERMODE_LIGHTMAP;
1206 if (rsurface.texture->currentskinframe->glow)
1207 permutation |= SHADERPERMUTATION_GLOW;
1208 if (r_refdef.fogenabled)
1209 permutation |= SHADERPERMUTATION_FOG;
1210 if (rsurface.texture->colormapping)
1211 permutation |= SHADERPERMUTATION_COLORMAPPING;
1212 if (r_glsl_offsetmapping.integer)
1214 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1215 if (r_glsl_offsetmapping_reliefmapping.integer)
1216 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1218 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1219 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1221 permutation |= SHADERPERMUTATION_REFLECTION;
1223 else if (modellighting)
1225 // directional model lighting
1226 mode = SHADERMODE_LIGHTDIRECTION;
1227 if (rsurface.texture->currentskinframe->glow)
1228 permutation |= SHADERPERMUTATION_GLOW;
1229 if (specularscale > 0)
1230 permutation |= SHADERPERMUTATION_SPECULAR;
1231 if (r_refdef.fogenabled)
1232 permutation |= SHADERPERMUTATION_FOG;
1233 if (rsurface.texture->colormapping)
1234 permutation |= SHADERPERMUTATION_COLORMAPPING;
1235 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1236 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1237 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1238 permutation |= SHADERPERMUTATION_REFLECTION;
1243 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1245 // deluxemapping (light direction texture)
1246 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1247 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1249 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1250 if (specularscale > 0)
1251 permutation |= SHADERPERMUTATION_SPECULAR;
1253 else if (r_glsl_deluxemapping.integer >= 2)
1255 // fake deluxemapping (uniform light direction in tangentspace)
1256 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1257 if (specularscale > 0)
1258 permutation |= SHADERPERMUTATION_SPECULAR;
1262 // ordinary lightmapping
1263 mode = SHADERMODE_LIGHTMAP;
1265 if (rsurface.texture->currentskinframe->glow)
1266 permutation |= SHADERPERMUTATION_GLOW;
1267 if (r_refdef.fogenabled)
1268 permutation |= SHADERPERMUTATION_FOG;
1269 if (rsurface.texture->colormapping)
1270 permutation |= SHADERPERMUTATION_COLORMAPPING;
1271 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1272 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1274 permutation |= SHADERPERMUTATION_REFLECTION;
1276 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1277 if (!r_glsl_permutations[permutation].program)
1279 if (!r_glsl_permutations[permutation].compiled)
1280 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1281 if (!r_glsl_permutations[permutation].program)
1283 // remove features until we find a valid permutation
1285 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1289 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");
1290 Cvar_SetValueQuick(&r_glsl, 0);
1291 return 0; // no bit left to clear
1293 // reduce i more quickly whenever it would not remove any bits
1294 if (!(permutation & i))
1297 if (!r_glsl_permutations[permutation].compiled)
1298 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1299 if (r_glsl_permutations[permutation].program)
1304 r_glsl_permutation = r_glsl_permutations + permutation;
1306 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1307 if (mode == SHADERMODE_LIGHTSOURCE)
1309 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1310 if (permutation & SHADERPERMUTATION_DIFFUSE)
1312 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1313 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1314 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1315 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1319 // ambient only is simpler
1320 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1321 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1322 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1323 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1326 else if (mode == SHADERMODE_LIGHTDIRECTION)
1328 if (r_glsl_permutation->loc_AmbientColor >= 0)
1329 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1330 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1331 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1332 if (r_glsl_permutation->loc_SpecularColor >= 0)
1333 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1334 if (r_glsl_permutation->loc_LightDir >= 0)
1335 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1339 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1340 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1341 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1343 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1344 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1346 // The formula used is actually:
1347 // color.rgb *= SceneBrightness;
1348 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1349 // I simplify that to
1350 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1351 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1353 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1354 // and do [[calculations]] here in the engine
1355 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1356 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1359 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1360 if (r_glsl_permutation->loc_FogColor >= 0)
1362 // additive passes are only darkened by fog, not tinted
1363 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1364 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1369 // color.rgb *= SceneBrightness;
1370 VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1371 if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1373 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1374 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1375 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1376 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1378 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1381 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1383 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1384 if (r_glsl_permutation->loc_Color_Pants >= 0)
1386 if (rsurface.texture->currentskinframe->pants)
1387 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1389 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1391 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1393 if (rsurface.texture->currentskinframe->shirt)
1394 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1396 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1398 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1399 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1400 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1401 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1402 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1403 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1404 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1405 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1406 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1407 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1412 #define SKINFRAME_HASH 1024
1416 int loadsequence; // incremented each level change
1417 memexpandablearray_t array;
1418 skinframe_t *hash[SKINFRAME_HASH];
1422 void R_SkinFrame_PrepareForPurge(void)
1424 r_skinframe.loadsequence++;
1425 // wrap it without hitting zero
1426 if (r_skinframe.loadsequence >= 200)
1427 r_skinframe.loadsequence = 1;
1430 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1434 // mark the skinframe as used for the purging code
1435 skinframe->loadsequence = r_skinframe.loadsequence;
1438 void R_SkinFrame_Purge(void)
1442 for (i = 0;i < SKINFRAME_HASH;i++)
1444 for (s = r_skinframe.hash[i];s;s = s->next)
1446 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1448 if (s->base == r_texture_notexture) s->base = NULL;
1449 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1450 if (s->merged == s->base) s->merged = NULL;
1451 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1452 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1453 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1454 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1455 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1456 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1457 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1458 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1459 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1460 s->loadsequence = 0;
1466 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1470 char basename[MAX_QPATH];
1472 Image_StripImageExtension(name, basename, sizeof(basename));
1474 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1475 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1476 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1482 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1483 memset(item, 0, sizeof(*item));
1484 strlcpy(item->basename, basename, sizeof(item->basename));
1485 item->textureflags = textureflags;
1486 item->comparewidth = comparewidth;
1487 item->compareheight = compareheight;
1488 item->comparecrc = comparecrc;
1489 item->next = r_skinframe.hash[hashindex];
1490 r_skinframe.hash[hashindex] = item;
1492 R_SkinFrame_MarkUsed(item);
1496 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1498 // FIXME: it should be possible to disable loading various layers using
1499 // cvars, to prevent wasted loading time and memory usage if the user does
1501 qboolean loadnormalmap = true;
1502 qboolean loadgloss = true;
1503 qboolean loadpantsandshirt = true;
1504 qboolean loadglow = true;
1506 unsigned char *pixels;
1507 unsigned char *bumppixels;
1508 unsigned char *basepixels = NULL;
1509 int basepixels_width;
1510 int basepixels_height;
1511 skinframe_t *skinframe;
1513 if (cls.state == ca_dedicated)
1516 // return an existing skinframe if already loaded
1517 // if loading of the first image fails, don't make a new skinframe as it
1518 // would cause all future lookups of this to be missing
1519 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1520 if (skinframe && skinframe->base)
1523 basepixels = loadimagepixels(name, complain, 0, 0);
1524 if (basepixels == NULL)
1527 // we've got some pixels to store, so really allocate this new texture now
1529 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1530 skinframe->stain = NULL;
1531 skinframe->merged = NULL;
1532 skinframe->base = r_texture_notexture;
1533 skinframe->pants = NULL;
1534 skinframe->shirt = NULL;
1535 skinframe->nmap = r_texture_blanknormalmap;
1536 skinframe->gloss = NULL;
1537 skinframe->glow = NULL;
1538 skinframe->fog = NULL;
1540 basepixels_width = image_width;
1541 basepixels_height = image_height;
1542 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);
1544 if (textureflags & TEXF_ALPHA)
1546 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1547 if (basepixels[j] < 255)
1549 if (j < basepixels_width * basepixels_height * 4)
1551 // has transparent pixels
1552 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1553 for (j = 0;j < image_width * image_height * 4;j += 4)
1558 pixels[j+3] = basepixels[j+3];
1560 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);
1565 // _norm is the name used by tenebrae and has been adopted as standard
1568 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1570 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);
1574 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1576 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1577 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1578 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);
1580 Mem_Free(bumppixels);
1582 else if (r_shadow_bumpscale_basetexture.value > 0)
1584 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1585 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1586 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);
1590 // _luma is supported for tenebrae compatibility
1591 // (I think it's a very stupid name, but oh well)
1592 // _glow is the preferred name
1593 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;}
1594 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;}
1595 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;}
1596 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;}
1599 Mem_Free(basepixels);
1604 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)
1609 for (i = 0;i < width*height;i++)
1610 if (((unsigned char *)&palette[in[i]])[3] > 0)
1612 if (i == width*height)
1615 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1618 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)
1621 unsigned char *temp1, *temp2;
1622 skinframe_t *skinframe;
1624 if (cls.state == ca_dedicated)
1627 // if already loaded just return it, otherwise make a new skinframe
1628 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1629 if (skinframe && skinframe->base)
1632 skinframe->stain = NULL;
1633 skinframe->merged = NULL;
1634 skinframe->base = r_texture_notexture;
1635 skinframe->pants = NULL;
1636 skinframe->shirt = NULL;
1637 skinframe->nmap = r_texture_blanknormalmap;
1638 skinframe->gloss = NULL;
1639 skinframe->glow = NULL;
1640 skinframe->fog = NULL;
1642 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1646 if (bitsperpixel == 32)
1648 if (r_shadow_bumpscale_basetexture.value > 0)
1650 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1651 temp2 = temp1 + width * height * 4;
1652 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1653 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1656 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1657 if (textureflags & TEXF_ALPHA)
1659 for (i = 3;i < width * height * 4;i += 4)
1660 if (skindata[i] < 255)
1662 if (i < width * height * 4)
1664 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1665 memcpy(fogpixels, skindata, width * height * 4);
1666 for (i = 0;i < width * height * 4;i += 4)
1667 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1668 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1669 Mem_Free(fogpixels);
1673 else if (bitsperpixel == 8)
1675 if (r_shadow_bumpscale_basetexture.value > 0)
1677 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1678 temp2 = temp1 + width * height * 4;
1679 if (bitsperpixel == 32)
1680 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1683 // use either a custom palette or the quake palette
1684 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1685 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1687 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1690 // use either a custom palette, or the quake palette
1691 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
1692 if (!palette && loadglowtexture)
1693 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1694 if (!palette && loadpantsandshirt)
1696 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1697 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1699 if (skinframe->pants || skinframe->shirt)
1700 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1701 if (textureflags & TEXF_ALPHA)
1703 // if not using a custom alphapalette, use the quake one
1705 alphapalette = palette_alpha;
1706 for (i = 0;i < width * height;i++)
1707 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1709 if (i < width * height)
1710 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1717 skinframe_t *R_SkinFrame_LoadMissing(void)
1719 skinframe_t *skinframe;
1721 if (cls.state == ca_dedicated)
1724 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1725 skinframe->stain = NULL;
1726 skinframe->merged = NULL;
1727 skinframe->base = r_texture_notexture;
1728 skinframe->pants = NULL;
1729 skinframe->shirt = NULL;
1730 skinframe->nmap = r_texture_blanknormalmap;
1731 skinframe->gloss = NULL;
1732 skinframe->glow = NULL;
1733 skinframe->fog = NULL;
1738 void gl_main_start(void)
1743 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1744 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1746 alpha = 1 - exp(r / ((double)x*(double)x));
1747 if (x == FOGMASKTABLEWIDTH - 1)
1749 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1752 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1753 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1755 // set up r_skinframe loading system for textures
1756 memset(&r_skinframe, 0, sizeof(r_skinframe));
1757 r_skinframe.loadsequence = 1;
1758 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1760 r_main_texturepool = R_AllocTexturePool();
1761 R_BuildBlankTextures();
1763 if (gl_texturecubemap)
1766 R_BuildNormalizationCube();
1768 R_BuildFogTexture();
1769 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1770 memset(&r_waterstate, 0, sizeof(r_waterstate));
1771 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1772 memset(&r_svbsp, 0, sizeof (r_svbsp));
1775 void gl_main_shutdown(void)
1777 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1778 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1780 // clear out the r_skinframe state
1781 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1782 memset(&r_skinframe, 0, sizeof(r_skinframe));
1785 Mem_Free(r_svbsp.nodes);
1786 memset(&r_svbsp, 0, sizeof (r_svbsp));
1787 R_FreeTexturePool(&r_main_texturepool);
1788 r_texture_blanknormalmap = NULL;
1789 r_texture_white = NULL;
1790 r_texture_grey128 = NULL;
1791 r_texture_black = NULL;
1792 r_texture_whitecube = NULL;
1793 r_texture_normalizationcube = NULL;
1794 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1795 memset(&r_waterstate, 0, sizeof(r_waterstate));
1799 extern void CL_ParseEntityLump(char *entitystring);
1800 void gl_main_newmap(void)
1802 // FIXME: move this code to client
1804 char *entities, entname[MAX_QPATH];
1807 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1808 l = (int)strlen(entname) - 4;
1809 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1811 memcpy(entname + l, ".ent", 5);
1812 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1814 CL_ParseEntityLump(entities);
1819 if (cl.worldmodel->brush.entities)
1820 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1824 void GL_Main_Init(void)
1826 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1828 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1829 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1830 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1831 if (gamemode == GAME_NEHAHRA)
1833 Cvar_RegisterVariable (&gl_fogenable);
1834 Cvar_RegisterVariable (&gl_fogdensity);
1835 Cvar_RegisterVariable (&gl_fogred);
1836 Cvar_RegisterVariable (&gl_foggreen);
1837 Cvar_RegisterVariable (&gl_fogblue);
1838 Cvar_RegisterVariable (&gl_fogstart);
1839 Cvar_RegisterVariable (&gl_fogend);
1841 Cvar_RegisterVariable(&r_depthfirst);
1842 Cvar_RegisterVariable(&r_nearclip);
1843 Cvar_RegisterVariable(&r_showbboxes);
1844 Cvar_RegisterVariable(&r_showsurfaces);
1845 Cvar_RegisterVariable(&r_showtris);
1846 Cvar_RegisterVariable(&r_shownormals);
1847 Cvar_RegisterVariable(&r_showlighting);
1848 Cvar_RegisterVariable(&r_showshadowvolumes);
1849 Cvar_RegisterVariable(&r_showcollisionbrushes);
1850 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1851 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1852 Cvar_RegisterVariable(&r_showdisabledepthtest);
1853 Cvar_RegisterVariable(&r_drawportals);
1854 Cvar_RegisterVariable(&r_drawentities);
1855 Cvar_RegisterVariable(&r_cullentities_trace);
1856 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1857 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1858 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1859 Cvar_RegisterVariable(&r_drawviewmodel);
1860 Cvar_RegisterVariable(&r_speeds);
1861 Cvar_RegisterVariable(&r_fullbrights);
1862 Cvar_RegisterVariable(&r_wateralpha);
1863 Cvar_RegisterVariable(&r_dynamic);
1864 Cvar_RegisterVariable(&r_fullbright);
1865 Cvar_RegisterVariable(&r_shadows);
1866 Cvar_RegisterVariable(&r_shadows_throwdistance);
1867 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1868 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1869 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1870 Cvar_RegisterVariable(&r_textureunits);
1871 Cvar_RegisterVariable(&r_glsl);
1872 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1873 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1874 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1875 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1876 Cvar_RegisterVariable(&r_water);
1877 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1878 Cvar_RegisterVariable(&r_water_clippingplanebias);
1879 Cvar_RegisterVariable(&r_water_refractdistort);
1880 Cvar_RegisterVariable(&r_water_reflectdistort);
1881 Cvar_RegisterVariable(&r_lerpsprites);
1882 Cvar_RegisterVariable(&r_lerpmodels);
1883 Cvar_RegisterVariable(&r_waterscroll);
1884 Cvar_RegisterVariable(&r_bloom);
1885 Cvar_RegisterVariable(&r_bloom_colorscale);
1886 Cvar_RegisterVariable(&r_bloom_brighten);
1887 Cvar_RegisterVariable(&r_bloom_blur);
1888 Cvar_RegisterVariable(&r_bloom_resolution);
1889 Cvar_RegisterVariable(&r_bloom_colorexponent);
1890 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1891 Cvar_RegisterVariable(&r_hdr);
1892 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1893 Cvar_RegisterVariable(&r_glsl_contrastboost);
1894 Cvar_RegisterVariable(&r_hdr_glowintensity);
1895 Cvar_RegisterVariable(&r_hdr_range);
1896 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1897 Cvar_RegisterVariable(&developer_texturelogging);
1898 Cvar_RegisterVariable(&gl_lightmaps);
1899 Cvar_RegisterVariable(&r_test);
1900 Cvar_RegisterVariable(&r_batchmode);
1901 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1902 Cvar_SetValue("r_fullbrights", 0);
1903 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1906 extern void R_Textures_Init(void);
1907 extern void GL_Draw_Init(void);
1908 extern void GL_Main_Init(void);
1909 extern void R_Shadow_Init(void);
1910 extern void R_Sky_Init(void);
1911 extern void GL_Surf_Init(void);
1912 extern void R_Light_Init(void);
1913 extern void R_Particles_Init(void);
1914 extern void R_Explosion_Init(void);
1915 extern void gl_backend_init(void);
1916 extern void Sbar_Init(void);
1917 extern void R_LightningBeams_Init(void);
1918 extern void Mod_RenderInit(void);
1920 void Render_Init(void)
1933 R_LightningBeams_Init();
1942 extern char *ENGINE_EXTENSIONS;
1945 VID_CheckExtensions();
1947 // LordHavoc: report supported extensions
1948 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1950 // clear to black (loading plaque will be seen over this)
1952 qglClearColor(0,0,0,1);CHECKGLERROR
1953 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1956 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1960 for (i = 0;i < r_view.numfrustumplanes;i++)
1962 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1965 p = r_view.frustum + i;
1970 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1974 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1978 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1982 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1986 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1990 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1994 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1998 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2006 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2010 for (i = 0;i < numplanes;i++)
2017 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2021 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2025 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2029 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2033 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2037 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2041 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2045 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2053 //==================================================================================
2055 static void R_UpdateEntityLighting(entity_render_t *ent)
2057 vec3_t tempdiffusenormal;
2059 // fetch the lighting from the worldmodel data
2060 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));
2061 VectorClear(ent->modellight_diffuse);
2062 VectorClear(tempdiffusenormal);
2063 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2066 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2067 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2070 VectorSet(ent->modellight_ambient, 1, 1, 1);
2072 // move the light direction into modelspace coordinates for lighting code
2073 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2074 if(VectorLength2(ent->modellight_lightdir) > 0)
2076 VectorNormalize(ent->modellight_lightdir);
2080 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2083 // scale ambient and directional light contributions according to rendering variables
2084 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2085 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2086 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2087 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2088 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2089 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2092 static void R_View_UpdateEntityVisible (void)
2095 entity_render_t *ent;
2097 if (!r_drawentities.integer)
2100 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2101 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2103 // worldmodel can check visibility
2104 for (i = 0;i < r_refdef.numentities;i++)
2106 ent = r_refdef.entities[i];
2107 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));
2109 if(r_cullentities_trace.integer)
2111 for (i = 0;i < r_refdef.numentities;i++)
2113 ent = r_refdef.entities[i];
2114 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2116 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2117 ent->last_trace_visibility = realtime;
2118 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2119 r_viewcache.entityvisible[i] = 0;
2126 // no worldmodel or it can't check visibility
2127 for (i = 0;i < r_refdef.numentities;i++)
2129 ent = r_refdef.entities[i];
2130 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2134 // update entity lighting (even on hidden entities for r_shadows)
2135 for (i = 0;i < r_refdef.numentities;i++)
2136 R_UpdateEntityLighting(r_refdef.entities[i]);
2139 // only used if skyrendermasked, and normally returns false
2140 int R_DrawBrushModelsSky (void)
2143 entity_render_t *ent;
2145 if (!r_drawentities.integer)
2149 for (i = 0;i < r_refdef.numentities;i++)
2151 if (!r_viewcache.entityvisible[i])
2153 ent = r_refdef.entities[i];
2154 if (!ent->model || !ent->model->DrawSky)
2156 ent->model->DrawSky(ent);
2162 static void R_DrawNoModel(entity_render_t *ent);
2163 static void R_DrawModels(void)
2166 entity_render_t *ent;
2168 if (!r_drawentities.integer)
2171 for (i = 0;i < r_refdef.numentities;i++)
2173 if (!r_viewcache.entityvisible[i])
2175 ent = r_refdef.entities[i];
2176 r_refdef.stats.entities++;
2177 if (ent->model && ent->model->Draw != NULL)
2178 ent->model->Draw(ent);
2184 static void R_DrawModelsDepth(void)
2187 entity_render_t *ent;
2189 if (!r_drawentities.integer)
2192 for (i = 0;i < r_refdef.numentities;i++)
2194 if (!r_viewcache.entityvisible[i])
2196 ent = r_refdef.entities[i];
2197 r_refdef.stats.entities++;
2198 if (ent->model && ent->model->DrawDepth != NULL)
2199 ent->model->DrawDepth(ent);
2203 static void R_DrawModelsDebug(void)
2206 entity_render_t *ent;
2208 if (!r_drawentities.integer)
2211 for (i = 0;i < r_refdef.numentities;i++)
2213 if (!r_viewcache.entityvisible[i])
2215 ent = r_refdef.entities[i];
2216 r_refdef.stats.entities++;
2217 if (ent->model && ent->model->DrawDebug != NULL)
2218 ent->model->DrawDebug(ent);
2222 static void R_DrawModelsAddWaterPlanes(void)
2225 entity_render_t *ent;
2227 if (!r_drawentities.integer)
2230 for (i = 0;i < r_refdef.numentities;i++)
2232 if (!r_viewcache.entityvisible[i])
2234 ent = r_refdef.entities[i];
2235 r_refdef.stats.entities++;
2236 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2237 ent->model->DrawAddWaterPlanes(ent);
2241 static void R_View_SetFrustum(void)
2244 double slopex, slopey;
2246 // break apart the view matrix into vectors for various purposes
2247 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2248 VectorNegate(r_view.left, r_view.right);
2251 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2252 r_view.frustum[0].normal[1] = 0 - 0;
2253 r_view.frustum[0].normal[2] = -1 - 0;
2254 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2255 r_view.frustum[1].normal[1] = 0 + 0;
2256 r_view.frustum[1].normal[2] = -1 + 0;
2257 r_view.frustum[2].normal[0] = 0 - 0;
2258 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2259 r_view.frustum[2].normal[2] = -1 - 0;
2260 r_view.frustum[3].normal[0] = 0 + 0;
2261 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2262 r_view.frustum[3].normal[2] = -1 + 0;
2266 zNear = r_refdef.nearclip;
2267 nudge = 1.0 - 1.0 / (1<<23);
2268 r_view.frustum[4].normal[0] = 0 - 0;
2269 r_view.frustum[4].normal[1] = 0 - 0;
2270 r_view.frustum[4].normal[2] = -1 - -nudge;
2271 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2272 r_view.frustum[5].normal[0] = 0 + 0;
2273 r_view.frustum[5].normal[1] = 0 + 0;
2274 r_view.frustum[5].normal[2] = -1 + -nudge;
2275 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2281 r_view.frustum[0].normal[0] = m[3] - m[0];
2282 r_view.frustum[0].normal[1] = m[7] - m[4];
2283 r_view.frustum[0].normal[2] = m[11] - m[8];
2284 r_view.frustum[0].dist = m[15] - m[12];
2286 r_view.frustum[1].normal[0] = m[3] + m[0];
2287 r_view.frustum[1].normal[1] = m[7] + m[4];
2288 r_view.frustum[1].normal[2] = m[11] + m[8];
2289 r_view.frustum[1].dist = m[15] + m[12];
2291 r_view.frustum[2].normal[0] = m[3] - m[1];
2292 r_view.frustum[2].normal[1] = m[7] - m[5];
2293 r_view.frustum[2].normal[2] = m[11] - m[9];
2294 r_view.frustum[2].dist = m[15] - m[13];
2296 r_view.frustum[3].normal[0] = m[3] + m[1];
2297 r_view.frustum[3].normal[1] = m[7] + m[5];
2298 r_view.frustum[3].normal[2] = m[11] + m[9];
2299 r_view.frustum[3].dist = m[15] + m[13];
2301 r_view.frustum[4].normal[0] = m[3] - m[2];
2302 r_view.frustum[4].normal[1] = m[7] - m[6];
2303 r_view.frustum[4].normal[2] = m[11] - m[10];
2304 r_view.frustum[4].dist = m[15] - m[14];
2306 r_view.frustum[5].normal[0] = m[3] + m[2];
2307 r_view.frustum[5].normal[1] = m[7] + m[6];
2308 r_view.frustum[5].normal[2] = m[11] + m[10];
2309 r_view.frustum[5].dist = m[15] + m[14];
2314 if (r_view.useperspective)
2316 slopex = 1.0 / r_view.frustum_x;
2317 slopey = 1.0 / r_view.frustum_y;
2318 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2319 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2320 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2321 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2322 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2324 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2325 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2326 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2327 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2328 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2330 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2331 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2332 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2333 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2334 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2338 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2339 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2340 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2341 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2342 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2343 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2344 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2345 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2346 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2347 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2349 r_view.numfrustumplanes = 5;
2351 if (r_view.useclipplane)
2353 r_view.numfrustumplanes = 6;
2354 r_view.frustum[5] = r_view.clipplane;
2357 for (i = 0;i < r_view.numfrustumplanes;i++)
2358 PlaneClassify(r_view.frustum + i);
2360 // LordHavoc: note to all quake engine coders, Quake had a special case
2361 // for 90 degrees which assumed a square view (wrong), so I removed it,
2362 // Quake2 has it disabled as well.
2364 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2365 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2366 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2367 //PlaneClassify(&frustum[0]);
2369 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2370 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2371 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2372 //PlaneClassify(&frustum[1]);
2374 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2375 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2376 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2377 //PlaneClassify(&frustum[2]);
2379 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2380 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2381 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2382 //PlaneClassify(&frustum[3]);
2385 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2386 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2387 //PlaneClassify(&frustum[4]);
2390 void R_View_Update(void)
2392 R_View_SetFrustum();
2393 R_View_WorldVisibility(r_view.useclipplane);
2394 R_View_UpdateEntityVisible();
2397 void R_SetupView(void)
2399 if (!r_view.useperspective)
2400 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);
2401 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2402 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2404 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2406 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2408 if (r_view.useclipplane)
2410 // LordHavoc: couldn't figure out how to make this approach the
2411 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2412 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2413 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2414 dist = r_view.clipplane.dist;
2415 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2419 void R_ResetViewRendering2D(void)
2421 if (gl_support_fragment_shader)
2423 qglUseProgramObjectARB(0);CHECKGLERROR
2428 // GL is weird because it's bottom to top, r_view.y is top to bottom
2429 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2430 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2431 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2432 GL_Color(1, 1, 1, 1);
2433 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2434 GL_BlendFunc(GL_ONE, GL_ZERO);
2435 GL_AlphaTest(false);
2436 GL_ScissorTest(false);
2437 GL_DepthMask(false);
2438 GL_DepthRange(0, 1);
2439 GL_DepthTest(false);
2440 R_Mesh_Matrix(&identitymatrix);
2441 R_Mesh_ResetTextureState();
2442 GL_PolygonOffset(0, 0);
2443 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2444 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2445 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2446 qglStencilMask(~0);CHECKGLERROR
2447 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2448 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2449 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2452 void R_ResetViewRendering3D(void)
2454 if (gl_support_fragment_shader)
2456 qglUseProgramObjectARB(0);CHECKGLERROR
2461 // GL is weird because it's bottom to top, r_view.y is top to bottom
2462 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2464 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2465 GL_Color(1, 1, 1, 1);
2466 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2467 GL_BlendFunc(GL_ONE, GL_ZERO);
2468 GL_AlphaTest(false);
2469 GL_ScissorTest(true);
2471 GL_DepthRange(0, 1);
2473 R_Mesh_Matrix(&identitymatrix);
2474 R_Mesh_ResetTextureState();
2475 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2476 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2477 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2478 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2479 qglStencilMask(~0);CHECKGLERROR
2480 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2481 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2482 GL_CullFace(r_view.cullface_back);
2486 R_Bloom_SetupShader(
2488 "// written by Forest 'LordHavoc' Hale\n"
2490 "// common definitions between vertex shader and fragment shader:\n"
2492 "#ifdef __GLSL_CG_DATA_TYPES\n"
2493 "#define myhalf half\n"
2494 "#define myhvec2 hvec2\n"
2495 "#define myhvec3 hvec3\n"
2496 "#define myhvec4 hvec4\n"
2498 "#define myhalf float\n"
2499 "#define myhvec2 vec2\n"
2500 "#define myhvec3 vec3\n"
2501 "#define myhvec4 vec4\n"
2504 "varying vec2 ScreenTexCoord;\n"
2505 "varying vec2 BloomTexCoord;\n"
2510 "// vertex shader specific:\n"
2511 "#ifdef VERTEX_SHADER\n"
2515 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2516 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2517 " // transform vertex to camera space, using ftransform to match non-VS\n"
2519 " gl_Position = ftransform();\n"
2522 "#endif // VERTEX_SHADER\n"
2527 "// fragment shader specific:\n"
2528 "#ifdef FRAGMENT_SHADER\n"
2533 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2534 " for (x = -BLUR_X;x <= BLUR_X;x++)
2535 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2536 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2537 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2538 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2540 " gl_FragColor = vec4(color);\n"
2543 "#endif // FRAGMENT_SHADER\n"
2546 void R_RenderScene(qboolean addwaterplanes);
2548 static void R_Water_StartFrame(void)
2551 int waterwidth, waterheight, texturewidth, textureheight;
2552 r_waterstate_waterplane_t *p;
2554 // set waterwidth and waterheight to the water resolution that will be
2555 // used (often less than the screen resolution for faster rendering)
2556 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2557 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2559 // calculate desired texture sizes
2560 // can't use water if the card does not support the texture size
2561 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2562 texturewidth = textureheight = waterwidth = waterheight = 0;
2563 else if (gl_support_arb_texture_non_power_of_two)
2565 texturewidth = waterwidth;
2566 textureheight = waterheight;
2570 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2571 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2574 // allocate textures as needed
2575 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2577 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2578 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2580 if (p->texture_refraction)
2581 R_FreeTexture(p->texture_refraction);
2582 p->texture_refraction = NULL;
2583 if (p->texture_reflection)
2584 R_FreeTexture(p->texture_reflection);
2585 p->texture_reflection = NULL;
2587 memset(&r_waterstate, 0, sizeof(r_waterstate));
2588 r_waterstate.waterwidth = waterwidth;
2589 r_waterstate.waterheight = waterheight;
2590 r_waterstate.texturewidth = texturewidth;
2591 r_waterstate.textureheight = textureheight;
2594 if (r_waterstate.waterwidth)
2596 r_waterstate.enabled = true;
2598 // set up variables that will be used in shader setup
2599 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2600 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2601 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2602 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2605 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2606 r_waterstate.numwaterplanes = 0;
2609 static void R_Water_AddWaterPlane(msurface_t *surface)
2611 int triangleindex, planeindex;
2617 r_waterstate_waterplane_t *p;
2618 // just use the first triangle with a valid normal for any decisions
2619 VectorClear(normal);
2620 VectorClear(center);
2621 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2623 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2624 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2625 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2626 TriangleNormal(vert[0], vert[1], vert[2], normal);
2627 if (VectorLength2(normal) >= 0.001)
2630 // now find the center of this surface
2631 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2634 VectorAdd(center, vert[0], center);
2636 f = 1.0 / surface->num_triangles*3;
2637 VectorScale(center, f, center);
2639 // find a matching plane if there is one
2640 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2641 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2643 if (planeindex >= r_waterstate.maxwaterplanes)
2644 return; // nothing we can do, out of planes
2646 // if this triangle does not fit any known plane rendered this frame, add one
2647 if (planeindex >= r_waterstate.numwaterplanes)
2649 // store the new plane
2650 r_waterstate.numwaterplanes++;
2651 VectorCopy(normal, p->plane.normal);
2652 VectorNormalize(p->plane.normal);
2653 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2654 PlaneClassify(&p->plane);
2655 // flip the plane if it does not face the viewer
2656 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2658 VectorNegate(p->plane.normal, p->plane.normal);
2659 p->plane.dist *= -1;
2660 PlaneClassify(&p->plane);
2662 // clear materialflags and pvs
2663 p->materialflags = 0;
2664 p->pvsvalid = false;
2666 // merge this surface's materialflags into the waterplane
2667 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2668 // merge this surface's PVS into the waterplane
2669 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2671 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2676 static void R_Water_ProcessPlanes(void)
2678 r_view_t originalview;
2680 r_waterstate_waterplane_t *p;
2682 originalview = r_view;
2684 // make sure enough textures are allocated
2685 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2687 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2689 if (!p->texture_refraction)
2690 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2691 if (!p->texture_refraction)
2695 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2697 if (!p->texture_reflection)
2698 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2699 if (!p->texture_reflection)
2705 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2707 r_view.showdebug = false;
2708 r_view.width = r_waterstate.waterwidth;
2709 r_view.height = r_waterstate.waterheight;
2710 r_view.useclipplane = true;
2711 r_waterstate.renderingscene = true;
2713 // render the normal view scene and copy into texture
2714 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
2715 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2717 r_view.clipplane = p->plane;
2718 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2719 r_view.clipplane.dist = -r_view.clipplane.dist;
2720 PlaneClassify(&r_view.clipplane);
2722 R_RenderScene(false);
2724 // copy view into the screen texture
2725 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2726 GL_ActiveTexture(0);
2728 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
2731 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2733 // render reflected scene and copy into texture
2734 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2735 r_view.clipplane = p->plane;
2736 // reverse the cullface settings for this render
2737 r_view.cullface_front = GL_FRONT;
2738 r_view.cullface_back = GL_BACK;
2739 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2741 r_view.usecustompvs = true;
2743 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2745 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2748 R_ResetViewRendering3D();
2751 R_RenderScene(false);
2753 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2754 GL_ActiveTexture(0);
2756 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
2758 R_ResetViewRendering3D();
2762 r_view = originalview;
2763 r_waterstate.renderingscene = false;
2767 r_view = originalview;
2768 r_waterstate.renderingscene = false;
2769 Cvar_SetValueQuick(&r_water, 0);
2770 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2774 void R_Bloom_StartFrame(void)
2776 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2778 // set bloomwidth and bloomheight to the bloom resolution that will be
2779 // used (often less than the screen resolution for faster rendering)
2780 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2781 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2782 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2784 // calculate desired texture sizes
2785 if (gl_support_arb_texture_non_power_of_two)
2787 screentexturewidth = r_view.width;
2788 screentextureheight = r_view.height;
2789 bloomtexturewidth = r_bloomstate.bloomwidth;
2790 bloomtextureheight = r_bloomstate.bloomheight;
2794 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2795 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2796 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2797 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2802 screentexturewidth = screentextureheight = 0;
2804 else if (r_bloom.integer)
2809 screentexturewidth = screentextureheight = 0;
2810 bloomtexturewidth = bloomtextureheight = 0;
2813 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)
2815 // can't use bloom if the parameters are too weird
2816 // can't use bloom if the card does not support the texture size
2817 if (r_bloomstate.texture_screen)
2818 R_FreeTexture(r_bloomstate.texture_screen);
2819 if (r_bloomstate.texture_bloom)
2820 R_FreeTexture(r_bloomstate.texture_bloom);
2821 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2825 r_bloomstate.enabled = true;
2826 r_bloomstate.hdr = r_hdr.integer != 0;
2828 // allocate textures as needed
2829 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2831 if (r_bloomstate.texture_screen)
2832 R_FreeTexture(r_bloomstate.texture_screen);
2833 r_bloomstate.texture_screen = NULL;
2834 r_bloomstate.screentexturewidth = screentexturewidth;
2835 r_bloomstate.screentextureheight = screentextureheight;
2836 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2837 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);
2839 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2841 if (r_bloomstate.texture_bloom)
2842 R_FreeTexture(r_bloomstate.texture_bloom);
2843 r_bloomstate.texture_bloom = NULL;
2844 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2845 r_bloomstate.bloomtextureheight = bloomtextureheight;
2846 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2847 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);
2850 // set up a texcoord array for the full resolution screen image
2851 // (we have to keep this around to copy back during final render)
2852 r_bloomstate.screentexcoord2f[0] = 0;
2853 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2854 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2855 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2856 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2857 r_bloomstate.screentexcoord2f[5] = 0;
2858 r_bloomstate.screentexcoord2f[6] = 0;
2859 r_bloomstate.screentexcoord2f[7] = 0;
2861 // set up a texcoord array for the reduced resolution bloom image
2862 // (which will be additive blended over the screen image)
2863 r_bloomstate.bloomtexcoord2f[0] = 0;
2864 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2865 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2866 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2867 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2868 r_bloomstate.bloomtexcoord2f[5] = 0;
2869 r_bloomstate.bloomtexcoord2f[6] = 0;
2870 r_bloomstate.bloomtexcoord2f[7] = 0;
2873 void R_Bloom_CopyScreenTexture(float colorscale)
2875 r_refdef.stats.bloom++;
2877 R_ResetViewRendering2D();
2878 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2879 R_Mesh_ColorPointer(NULL, 0, 0);
2880 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2881 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2883 // copy view into the screen texture
2884 GL_ActiveTexture(0);
2886 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
2887 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2889 // now scale it down to the bloom texture size
2891 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2892 GL_BlendFunc(GL_ONE, GL_ZERO);
2893 GL_Color(colorscale, colorscale, colorscale, 1);
2894 // TODO: optimize with multitexture or GLSL
2895 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2896 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2898 // we now have a bloom image in the framebuffer
2899 // copy it into the bloom image texture for later processing
2900 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2901 GL_ActiveTexture(0);
2903 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
2904 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2907 void R_Bloom_CopyHDRTexture(void)
2909 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2910 GL_ActiveTexture(0);
2912 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
2913 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2916 void R_Bloom_MakeTexture(void)
2919 float xoffset, yoffset, r, brighten;
2921 r_refdef.stats.bloom++;
2923 R_ResetViewRendering2D();
2924 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2925 R_Mesh_ColorPointer(NULL, 0, 0);
2927 // we have a bloom image in the framebuffer
2929 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2931 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2934 r = bound(0, r_bloom_colorexponent.value / x, 1);
2935 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2936 GL_Color(r, r, r, 1);
2937 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2938 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2939 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2940 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2942 // copy the vertically blurred bloom view to a texture
2943 GL_ActiveTexture(0);
2945 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
2946 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2949 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2950 brighten = r_bloom_brighten.value;
2952 brighten *= r_hdr_range.value;
2953 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2954 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2956 for (dir = 0;dir < 2;dir++)
2958 // blend on at multiple vertical offsets to achieve a vertical blur
2959 // TODO: do offset blends using GLSL
2960 GL_BlendFunc(GL_ONE, GL_ZERO);
2961 for (x = -range;x <= range;x++)
2963 if (!dir){xoffset = 0;yoffset = x;}
2964 else {xoffset = x;yoffset = 0;}
2965 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2966 yoffset /= (float)r_bloomstate.bloomtextureheight;
2967 // compute a texcoord array with the specified x and y offset
2968 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2969 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2970 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2971 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2972 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2973 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2974 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2975 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2976 // this r value looks like a 'dot' particle, fading sharply to
2977 // black at the edges
2978 // (probably not realistic but looks good enough)
2979 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2980 //r = (dir ? 1.0f : brighten)/(range*2+1);
2981 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2982 GL_Color(r, r, r, 1);
2983 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2984 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2985 GL_BlendFunc(GL_ONE, GL_ONE);
2988 // copy the vertically blurred bloom view to a texture
2989 GL_ActiveTexture(0);
2991 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
2992 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2995 // apply subtract last
2996 // (just like it would be in a GLSL shader)
2997 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2999 GL_BlendFunc(GL_ONE, GL_ZERO);
3000 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3001 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3002 GL_Color(1, 1, 1, 1);
3003 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3004 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3006 GL_BlendFunc(GL_ONE, GL_ONE);
3007 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3008 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3009 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3010 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3011 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3012 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3013 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3015 // copy the darkened bloom view to a texture
3016 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3017 GL_ActiveTexture(0);
3019 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
3020 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3024 void R_HDR_RenderBloomTexture(void)
3026 int oldwidth, oldheight;
3028 oldwidth = r_view.width;
3029 oldheight = r_view.height;
3030 r_view.width = r_bloomstate.bloomwidth;
3031 r_view.height = r_bloomstate.bloomheight;
3033 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3034 // TODO: add exposure compensation features
3035 // TODO: add fp16 framebuffer support
3037 r_view.showdebug = false;
3038 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3040 r_view.colorscale /= r_hdr_range.value;
3041 r_waterstate.numwaterplanes = 0;
3042 R_RenderScene(r_waterstate.enabled);
3043 r_view.showdebug = true;
3045 R_ResetViewRendering2D();
3047 R_Bloom_CopyHDRTexture();
3048 R_Bloom_MakeTexture();
3050 R_ResetViewRendering3D();
3053 if (r_timereport_active)
3054 R_TimeReport("clear");
3057 // restore the view settings
3058 r_view.width = oldwidth;
3059 r_view.height = oldheight;
3062 static void R_BlendView(void)
3064 if (r_bloomstate.enabled && r_bloomstate.hdr)
3066 // render high dynamic range bloom effect
3067 // the bloom texture was made earlier this render, so we just need to
3068 // blend it onto the screen...
3069 R_ResetViewRendering2D();
3070 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3071 R_Mesh_ColorPointer(NULL, 0, 0);
3072 GL_Color(1, 1, 1, 1);
3073 GL_BlendFunc(GL_ONE, GL_ONE);
3074 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3075 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3076 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3077 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3079 else if (r_bloomstate.enabled)
3081 // render simple bloom effect
3082 // copy the screen and shrink it and darken it for the bloom process
3083 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3084 // make the bloom texture
3085 R_Bloom_MakeTexture();
3086 // put the original screen image back in place and blend the bloom
3088 R_ResetViewRendering2D();
3089 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3090 R_Mesh_ColorPointer(NULL, 0, 0);
3091 GL_Color(1, 1, 1, 1);
3092 GL_BlendFunc(GL_ONE, GL_ZERO);
3093 // do both in one pass if possible
3094 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3095 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3096 if (r_textureunits.integer >= 2 && gl_combine.integer)
3098 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3099 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3100 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3104 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3105 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3106 // now blend on the bloom texture
3107 GL_BlendFunc(GL_ONE, GL_ONE);
3108 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3109 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3111 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3112 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3114 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3116 // apply a color tint to the whole view
3117 R_ResetViewRendering2D();
3118 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3119 R_Mesh_ColorPointer(NULL, 0, 0);
3120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3121 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3122 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3126 void R_RenderScene(qboolean addwaterplanes);
3128 matrix4x4_t r_waterscrollmatrix;
3130 void R_UpdateVariables(void)
3134 r_refdef.farclip = 4096;
3135 if (r_refdef.worldmodel)
3136 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3137 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3139 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3140 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3141 r_refdef.polygonfactor = 0;
3142 r_refdef.polygonoffset = 0;
3143 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3144 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3146 r_refdef.rtworld = r_shadow_realtime_world.integer;
3147 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3148 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3149 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3150 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3151 if (r_showsurfaces.integer)
3153 r_refdef.rtworld = false;
3154 r_refdef.rtworldshadows = false;
3155 r_refdef.rtdlight = false;
3156 r_refdef.rtdlightshadows = false;
3157 r_refdef.lightmapintensity = 0;
3160 if (gamemode == GAME_NEHAHRA)
3162 if (gl_fogenable.integer)
3164 r_refdef.oldgl_fogenable = true;
3165 r_refdef.fog_density = gl_fogdensity.value;
3166 r_refdef.fog_red = gl_fogred.value;
3167 r_refdef.fog_green = gl_foggreen.value;
3168 r_refdef.fog_blue = gl_fogblue.value;
3170 else if (r_refdef.oldgl_fogenable)
3172 r_refdef.oldgl_fogenable = false;
3173 r_refdef.fog_density = 0;
3174 r_refdef.fog_red = 0;
3175 r_refdef.fog_green = 0;
3176 r_refdef.fog_blue = 0;
3179 if (r_refdef.fog_density)
3181 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3182 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3183 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3185 if (r_refdef.fog_density)
3187 r_refdef.fogenabled = true;
3188 // this is the point where the fog reaches 0.9986 alpha, which we
3189 // consider a good enough cutoff point for the texture
3190 // (0.9986 * 256 == 255.6)
3191 r_refdef.fogrange = 400 / r_refdef.fog_density;
3192 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3193 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3194 // fog color was already set
3197 r_refdef.fogenabled = false;
3205 void R_RenderView(void)
3207 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3208 return; //Host_Error ("R_RenderView: NULL worldmodel");
3210 R_Shadow_UpdateWorldLightSelection();
3212 R_Bloom_StartFrame();
3213 R_Water_StartFrame();
3216 if (r_timereport_active)
3217 R_TimeReport("setup");
3219 R_ResetViewRendering3D();
3222 if (r_timereport_active)
3223 R_TimeReport("clear");
3225 r_view.showdebug = true;
3227 // this produces a bloom texture to be used in R_BlendView() later
3229 R_HDR_RenderBloomTexture();
3231 r_view.colorscale = r_hdr_scenebrightness.value;
3232 r_waterstate.numwaterplanes = 0;
3233 R_RenderScene(r_waterstate.enabled);
3236 if (r_timereport_active)
3237 R_TimeReport("blendview");
3239 GL_Scissor(0, 0, vid.width, vid.height);
3240 GL_ScissorTest(false);
3244 extern void R_DrawLightningBeams (void);
3245 extern void VM_CL_AddPolygonsToMeshQueue (void);
3246 extern void R_DrawPortals (void);
3247 extern cvar_t cl_locs_show;
3248 static void R_DrawLocs(void);
3249 static void R_DrawEntityBBoxes(void);
3250 void R_RenderScene(qboolean addwaterplanes)
3254 R_ResetViewRendering3D();
3257 if (r_timereport_active)
3258 R_TimeReport("watervisibility");
3260 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3262 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3263 if (r_timereport_active)
3264 R_TimeReport("waterworld");
3267 // don't let sound skip if going slow
3268 if (r_refdef.extraupdate)
3271 R_DrawModelsAddWaterPlanes();
3272 if (r_timereport_active)
3273 R_TimeReport("watermodels");
3275 R_Water_ProcessPlanes();
3276 if (r_timereport_active)
3277 R_TimeReport("waterscenes");
3280 R_ResetViewRendering3D();
3282 // don't let sound skip if going slow
3283 if (r_refdef.extraupdate)
3286 R_MeshQueue_BeginScene();
3291 if (r_timereport_active)
3292 R_TimeReport("visibility");
3294 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);
3296 if (cl.csqc_vidvars.drawworld)
3298 // don't let sound skip if going slow
3299 if (r_refdef.extraupdate)
3302 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3304 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3305 if (r_timereport_active)
3306 R_TimeReport("worldsky");
3309 if (R_DrawBrushModelsSky() && r_timereport_active)
3310 R_TimeReport("bmodelsky");
3313 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3315 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3316 if (r_timereport_active)
3317 R_TimeReport("worlddepth");
3319 if (r_depthfirst.integer >= 2)
3321 R_DrawModelsDepth();
3322 if (r_timereport_active)
3323 R_TimeReport("modeldepth");
3326 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3328 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3329 if (r_timereport_active)
3330 R_TimeReport("world");
3333 // don't let sound skip if going slow
3334 if (r_refdef.extraupdate)
3338 if (r_timereport_active)
3339 R_TimeReport("models");
3341 // don't let sound skip if going slow
3342 if (r_refdef.extraupdate)
3345 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3347 R_DrawModelShadows();
3349 R_ResetViewRendering3D();
3351 // don't let sound skip if going slow
3352 if (r_refdef.extraupdate)
3356 R_ShadowVolumeLighting(false);
3357 if (r_timereport_active)
3358 R_TimeReport("rtlights");
3360 // don't let sound skip if going slow
3361 if (r_refdef.extraupdate)
3364 if (cl.csqc_vidvars.drawworld)
3366 R_DrawLightningBeams();
3367 if (r_timereport_active)
3368 R_TimeReport("lightning");
3371 if (r_timereport_active)
3372 R_TimeReport("particles");
3375 if (r_timereport_active)
3376 R_TimeReport("explosions");
3379 if (gl_support_fragment_shader)
3381 qglUseProgramObjectARB(0);CHECKGLERROR
3383 VM_CL_AddPolygonsToMeshQueue();
3385 if (r_view.showdebug)
3387 if (cl_locs_show.integer)
3390 if (r_timereport_active)
3391 R_TimeReport("showlocs");
3394 if (r_drawportals.integer)
3397 if (r_timereport_active)
3398 R_TimeReport("portals");
3401 if (r_showbboxes.value > 0)
3403 R_DrawEntityBBoxes();
3404 if (r_timereport_active)
3405 R_TimeReport("bboxes");
3409 if (gl_support_fragment_shader)
3411 qglUseProgramObjectARB(0);CHECKGLERROR
3413 R_MeshQueue_RenderTransparent();
3414 if (r_timereport_active)
3415 R_TimeReport("drawtrans");
3417 if (gl_support_fragment_shader)
3419 qglUseProgramObjectARB(0);CHECKGLERROR
3422 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3424 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3425 if (r_timereport_active)
3426 R_TimeReport("worlddebug");
3427 R_DrawModelsDebug();
3428 if (r_timereport_active)
3429 R_TimeReport("modeldebug");
3432 if (gl_support_fragment_shader)
3434 qglUseProgramObjectARB(0);CHECKGLERROR
3437 if (cl.csqc_vidvars.drawworld)
3440 if (r_timereport_active)
3441 R_TimeReport("coronas");
3444 // don't let sound skip if going slow
3445 if (r_refdef.extraupdate)
3448 R_ResetViewRendering2D();
3451 static const int bboxelements[36] =
3461 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3464 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3465 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3466 GL_DepthMask(false);
3467 GL_DepthRange(0, 1);
3468 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3469 R_Mesh_Matrix(&identitymatrix);
3470 R_Mesh_ResetTextureState();
3472 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3473 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3474 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3475 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3476 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3477 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3478 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3479 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3480 R_FillColors(color4f, 8, cr, cg, cb, ca);
3481 if (r_refdef.fogenabled)
3483 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3485 f1 = FogPoint_World(v);
3487 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3488 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3489 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3492 R_Mesh_VertexPointer(vertex3f, 0, 0);
3493 R_Mesh_ColorPointer(color4f, 0, 0);
3494 R_Mesh_ResetTextureState();
3495 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3498 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3502 prvm_edict_t *edict;
3503 // this function draws bounding boxes of server entities
3507 for (i = 0;i < numsurfaces;i++)
3509 edict = PRVM_EDICT_NUM(surfacelist[i]);
3510 switch ((int)edict->fields.server->solid)
3512 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3513 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3514 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3515 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3516 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3517 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3519 color[3] *= r_showbboxes.value;
3520 color[3] = bound(0, color[3], 1);
3521 GL_DepthTest(!r_showdisabledepthtest.integer);
3522 GL_CullFace(r_view.cullface_front);
3523 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3528 static void R_DrawEntityBBoxes(void)
3531 prvm_edict_t *edict;
3533 // this function draws bounding boxes of server entities
3537 for (i = 0;i < prog->num_edicts;i++)
3539 edict = PRVM_EDICT_NUM(i);
3540 if (edict->priv.server->free)
3542 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3543 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3548 int nomodelelements[24] =
3560 float nomodelvertex3f[6*3] =
3570 float nomodelcolor4f[6*4] =
3572 0.0f, 0.0f, 0.5f, 1.0f,
3573 0.0f, 0.0f, 0.5f, 1.0f,
3574 0.0f, 0.5f, 0.0f, 1.0f,
3575 0.0f, 0.5f, 0.0f, 1.0f,
3576 0.5f, 0.0f, 0.0f, 1.0f,
3577 0.5f, 0.0f, 0.0f, 1.0f
3580 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3585 // this is only called once per entity so numsurfaces is always 1, and
3586 // surfacelist is always {0}, so this code does not handle batches
3587 R_Mesh_Matrix(&ent->matrix);
3589 if (ent->flags & EF_ADDITIVE)
3591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3592 GL_DepthMask(false);
3594 else if (ent->alpha < 1)
3596 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3597 GL_DepthMask(false);
3601 GL_BlendFunc(GL_ONE, GL_ZERO);
3604 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3605 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3606 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3607 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3608 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3609 if (r_refdef.fogenabled)
3612 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3613 R_Mesh_ColorPointer(color4f, 0, 0);
3614 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3615 f1 = FogPoint_World(org);
3617 for (i = 0, c = color4f;i < 6;i++, c += 4)
3619 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3620 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3621 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3625 else if (ent->alpha != 1)
3627 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3628 R_Mesh_ColorPointer(color4f, 0, 0);
3629 for (i = 0, c = color4f;i < 6;i++, c += 4)
3633 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3634 R_Mesh_ResetTextureState();
3635 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3638 void R_DrawNoModel(entity_render_t *ent)
3641 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3642 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3643 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3645 // R_DrawNoModelCallback(ent, 0);
3648 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3650 vec3_t right1, right2, diff, normal;
3652 VectorSubtract (org2, org1, normal);
3654 // calculate 'right' vector for start
3655 VectorSubtract (r_view.origin, org1, diff);
3656 CrossProduct (normal, diff, right1);
3657 VectorNormalize (right1);
3659 // calculate 'right' vector for end
3660 VectorSubtract (r_view.origin, org2, diff);
3661 CrossProduct (normal, diff, right2);
3662 VectorNormalize (right2);
3664 vert[ 0] = org1[0] + width * right1[0];
3665 vert[ 1] = org1[1] + width * right1[1];
3666 vert[ 2] = org1[2] + width * right1[2];
3667 vert[ 3] = org1[0] - width * right1[0];
3668 vert[ 4] = org1[1] - width * right1[1];
3669 vert[ 5] = org1[2] - width * right1[2];
3670 vert[ 6] = org2[0] - width * right2[0];
3671 vert[ 7] = org2[1] - width * right2[1];
3672 vert[ 8] = org2[2] - width * right2[2];
3673 vert[ 9] = org2[0] + width * right2[0];
3674 vert[10] = org2[1] + width * right2[1];
3675 vert[11] = org2[2] + width * right2[2];
3678 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3680 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)
3685 if (r_refdef.fogenabled)
3686 fog = FogPoint_World(origin);
3688 R_Mesh_Matrix(&identitymatrix);
3689 GL_BlendFunc(blendfunc1, blendfunc2);
3695 GL_CullFace(r_view.cullface_front);
3698 GL_CullFace(r_view.cullface_back);
3700 GL_DepthMask(false);
3701 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3702 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3703 GL_DepthTest(!depthdisable);
3705 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3706 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3707 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3708 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3709 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3710 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3711 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3712 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3713 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3714 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3715 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3716 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3718 R_Mesh_VertexPointer(vertex3f, 0, 0);
3719 R_Mesh_ColorPointer(NULL, 0, 0);
3720 R_Mesh_ResetTextureState();
3721 R_Mesh_TexBind(0, R_GetTexture(texture));
3722 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3723 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3724 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3725 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3727 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3729 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3730 GL_BlendFunc(blendfunc1, GL_ONE);
3732 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);
3733 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3737 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3742 VectorSet(v, x, y, z);
3743 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3744 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3746 if (i == mesh->numvertices)
3748 if (mesh->numvertices < mesh->maxvertices)
3750 VectorCopy(v, vertex3f);
3751 mesh->numvertices++;
3753 return mesh->numvertices;
3759 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3763 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3764 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3765 e = mesh->element3i + mesh->numtriangles * 3;
3766 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3768 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3769 if (mesh->numtriangles < mesh->maxtriangles)
3774 mesh->numtriangles++;
3776 element[1] = element[2];
3780 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3784 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3785 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3786 e = mesh->element3i + mesh->numtriangles * 3;
3787 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3789 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3790 if (mesh->numtriangles < mesh->maxtriangles)
3795 mesh->numtriangles++;
3797 element[1] = element[2];
3801 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3802 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3804 int planenum, planenum2;
3807 mplane_t *plane, *plane2;
3809 double temppoints[2][256*3];
3810 // figure out how large a bounding box we need to properly compute this brush
3812 for (w = 0;w < numplanes;w++)
3813 maxdist = max(maxdist, planes[w].dist);
3814 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3815 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3816 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3820 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3821 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3823 if (planenum2 == planenum)
3825 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);
3828 if (tempnumpoints < 3)
3830 // generate elements forming a triangle fan for this polygon
3831 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3835 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)
3837 texturelayer_t *layer;
3838 layer = t->currentlayers + t->currentnumlayers++;
3840 layer->depthmask = depthmask;
3841 layer->blendfunc1 = blendfunc1;
3842 layer->blendfunc2 = blendfunc2;
3843 layer->texture = texture;
3844 layer->texmatrix = *matrix;
3845 layer->color[0] = r * r_view.colorscale;
3846 layer->color[1] = g * r_view.colorscale;
3847 layer->color[2] = b * r_view.colorscale;
3848 layer->color[3] = a;
3851 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3854 index = parms[2] + r_refdef.time * parms[3];
3855 index -= floor(index);
3859 case Q3WAVEFUNC_NONE:
3860 case Q3WAVEFUNC_NOISE:
3861 case Q3WAVEFUNC_COUNT:
3864 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3865 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3866 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3867 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3868 case Q3WAVEFUNC_TRIANGLE:
3870 f = index - floor(index);
3881 return (float)(parms[0] + parms[1] * f);
3884 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3887 model_t *model = ent->model;
3890 q3shaderinfo_layer_tcmod_t *tcmod;
3892 // switch to an alternate material if this is a q1bsp animated material
3894 texture_t *texture = t;
3895 int s = ent->skinnum;
3896 if ((unsigned int)s >= (unsigned int)model->numskins)
3898 if (model->skinscenes)
3900 if (model->skinscenes[s].framecount > 1)
3901 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3903 s = model->skinscenes[s].firstframe;
3906 t = t + s * model->num_surfaces;
3909 // use an alternate animation if the entity's frame is not 0,
3910 // and only if the texture has an alternate animation
3911 if (ent->frame2 != 0 && t->anim_total[1])
3912 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3914 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3916 texture->currentframe = t;
3919 // update currentskinframe to be a qw skin or animation frame
3920 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3922 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3924 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3925 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3926 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);
3928 t->currentskinframe = r_qwskincache_skinframe[i];
3929 if (t->currentskinframe == NULL)
3930 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3932 else if (t->numskinframes >= 2)
3933 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3934 if (t->backgroundnumskinframes >= 2)
3935 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3937 t->currentmaterialflags = t->basematerialflags;
3938 t->currentalpha = ent->alpha;
3939 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3941 t->currentalpha *= r_wateralpha.value;
3943 * FIXME what is this supposed to do?
3944 // if rendering refraction/reflection, disable transparency
3945 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3946 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3949 if(!r_waterstate.enabled)
3950 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
3951 if (!(ent->flags & RENDER_LIGHT))
3952 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3953 if (ent->effects & EF_ADDITIVE)
3954 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3955 else if (t->currentalpha < 1)
3956 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3957 if (ent->effects & EF_DOUBLESIDED)
3958 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3959 if (ent->effects & EF_NODEPTHTEST)
3960 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3961 if (ent->flags & RENDER_VIEWMODEL)
3962 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3963 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3964 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3966 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3969 switch(tcmod->tcmod)
3973 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3974 matrix = r_waterscrollmatrix;
3976 matrix = identitymatrix;
3978 case Q3TCMOD_ENTITYTRANSLATE:
3979 // this is used in Q3 to allow the gamecode to control texcoord
3980 // scrolling on the entity, which is not supported in darkplaces yet.
3981 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3983 case Q3TCMOD_ROTATE:
3984 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3985 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3986 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3989 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3991 case Q3TCMOD_SCROLL:
3992 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3994 case Q3TCMOD_STRETCH:
3995 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3996 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3998 case Q3TCMOD_TRANSFORM:
3999 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4000 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4001 VectorSet(tcmat + 6, 0 , 0 , 1);
4002 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4003 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4005 case Q3TCMOD_TURBULENT:
4006 // this is handled in the RSurf_PrepareVertices function
4007 matrix = identitymatrix;
4010 // either replace or concatenate the transformation
4012 t->currenttexmatrix = matrix;
4015 matrix4x4_t temp = t->currenttexmatrix;
4016 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4020 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4021 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4022 t->glosstexture = r_texture_black;
4023 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4024 t->backgroundglosstexture = r_texture_black;
4025 t->specularpower = r_shadow_glossexponent.value;
4026 // TODO: store reference values for these in the texture?
4027 t->specularscale = 0;
4028 if (r_shadow_gloss.integer > 0)
4030 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4032 if (r_shadow_glossintensity.value > 0)
4034 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4035 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4036 t->specularscale = r_shadow_glossintensity.value;
4039 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4041 t->glosstexture = r_texture_white;
4042 t->backgroundglosstexture = r_texture_white;
4043 t->specularscale = r_shadow_gloss2intensity.value;
4047 // lightmaps mode looks bad with dlights using actual texturing, so turn
4048 // off the colormap and glossmap, but leave the normalmap on as it still
4049 // accurately represents the shading involved
4050 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4052 t->basetexture = r_texture_white;
4053 t->specularscale = 0;
4056 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4057 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4058 // submodels are biased to avoid z-fighting with world surfaces that they
4059 // may be exactly overlapping (avoids z-fighting artifacts on certain
4060 // doors and things in Quake maps)
4061 if (ent->model->brush.submodel)
4063 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4064 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4067 VectorClear(t->dlightcolor);
4068 t->currentnumlayers = 0;
4069 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4071 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4073 int blendfunc1, blendfunc2, depthmask;
4074 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4076 blendfunc1 = GL_SRC_ALPHA;
4077 blendfunc2 = GL_ONE;
4079 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4081 blendfunc1 = GL_SRC_ALPHA;
4082 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4084 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4086 blendfunc1 = t->customblendfunc[0];
4087 blendfunc2 = t->customblendfunc[1];
4091 blendfunc1 = GL_ONE;
4092 blendfunc2 = GL_ZERO;
4094 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4095 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4097 rtexture_t *currentbasetexture;
4099 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4100 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4101 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4102 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4104 // fullbright is not affected by r_refdef.lightmapintensity
4105 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4106 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4107 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);
4108 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4109 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);
4114 // set the color tint used for lights affecting this surface
4115 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4117 // q3bsp has no lightmap updates, so the lightstylevalue that
4118 // would normally be baked into the lightmap must be
4119 // applied to the color
4120 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4121 if (ent->model->type == mod_brushq3)
4122 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4123 colorscale *= r_refdef.lightmapintensity;
4124 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);
4125 if (r_ambient.value >= (1.0f/64.0f))
4126 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);
4127 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4129 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);
4130 if (r_ambient.value >= (1.0f/64.0f))
4131 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);
4133 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4135 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);
4136 if (r_ambient.value >= (1.0f/64.0f))
4137 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);
4140 if (t->currentskinframe->glow != NULL)
4141 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);
4142 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4144 // if this is opaque use alpha blend which will darken the earlier
4147 // if this is an alpha blended material, all the earlier passes
4148 // were darkened by fog already, so we only need to add the fog
4149 // color ontop through the fog mask texture
4151 // if this is an additive blended material, all the earlier passes
4152 // were darkened by fog already, and we should not add fog color
4153 // (because the background was not darkened, there is no fog color
4154 // that was lost behind it).
4155 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);
4162 void R_UpdateAllTextureInfo(entity_render_t *ent)
4166 for (i = 0;i < ent->model->num_texturesperskin;i++)
4167 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4170 rsurfacestate_t rsurface;
4172 void R_Mesh_ResizeArrays(int newvertices)
4175 if (rsurface.array_size >= newvertices)
4177 if (rsurface.array_modelvertex3f)
4178 Mem_Free(rsurface.array_modelvertex3f);
4179 rsurface.array_size = (newvertices + 1023) & ~1023;
4180 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4181 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4182 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4183 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4184 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4185 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4186 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4187 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4188 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4189 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4190 rsurface.array_color4f = base + rsurface.array_size * 27;
4191 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4194 void RSurf_CleanUp(void)
4197 if (rsurface.mode == RSURFMODE_GLSL)
4199 qglUseProgramObjectARB(0);CHECKGLERROR
4201 GL_AlphaTest(false);
4202 rsurface.mode = RSURFMODE_NONE;
4203 rsurface.uselightmaptexture = false;
4204 rsurface.texture = NULL;
4207 void RSurf_ActiveWorldEntity(void)
4209 model_t *model = r_refdef.worldmodel;
4211 if (rsurface.array_size < model->surfmesh.num_vertices)
4212 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4213 rsurface.matrix = identitymatrix;
4214 rsurface.inversematrix = identitymatrix;
4215 R_Mesh_Matrix(&identitymatrix);
4216 VectorCopy(r_view.origin, rsurface.modelorg);
4217 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4218 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4219 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4220 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4221 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4222 rsurface.frameblend[0].frame = 0;
4223 rsurface.frameblend[0].lerp = 1;
4224 rsurface.frameblend[1].frame = 0;
4225 rsurface.frameblend[1].lerp = 0;
4226 rsurface.frameblend[2].frame = 0;
4227 rsurface.frameblend[2].lerp = 0;
4228 rsurface.frameblend[3].frame = 0;
4229 rsurface.frameblend[3].lerp = 0;
4230 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4231 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4232 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4233 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4234 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4235 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4236 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4237 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4238 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4239 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4240 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4241 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4242 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4243 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4244 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4245 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4246 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4247 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4248 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4249 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4250 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4251 rsurface.modelelement3i = model->surfmesh.data_element3i;
4252 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4253 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4254 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4255 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4256 rsurface.modelsurfaces = model->data_surfaces;
4257 rsurface.generatedvertex = false;
4258 rsurface.vertex3f = rsurface.modelvertex3f;
4259 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4260 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4261 rsurface.svector3f = rsurface.modelsvector3f;
4262 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4263 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4264 rsurface.tvector3f = rsurface.modeltvector3f;
4265 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4266 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4267 rsurface.normal3f = rsurface.modelnormal3f;
4268 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4269 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4270 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4273 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4275 model_t *model = ent->model;
4277 if (rsurface.array_size < model->surfmesh.num_vertices)
4278 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4279 rsurface.matrix = ent->matrix;
4280 rsurface.inversematrix = ent->inversematrix;
4281 R_Mesh_Matrix(&rsurface.matrix);
4282 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4283 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4284 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4285 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4286 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4287 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4288 rsurface.frameblend[0] = ent->frameblend[0];
4289 rsurface.frameblend[1] = ent->frameblend[1];
4290 rsurface.frameblend[2] = ent->frameblend[2];
4291 rsurface.frameblend[3] = ent->frameblend[3];
4292 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4296 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4297 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4298 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4299 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4300 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4302 else if (wantnormals)
4304 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4305 rsurface.modelsvector3f = NULL;
4306 rsurface.modeltvector3f = NULL;
4307 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4308 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4312 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4313 rsurface.modelsvector3f = NULL;
4314 rsurface.modeltvector3f = NULL;
4315 rsurface.modelnormal3f = NULL;
4316 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4318 rsurface.modelvertex3f_bufferobject = 0;
4319 rsurface.modelvertex3f_bufferoffset = 0;
4320 rsurface.modelsvector3f_bufferobject = 0;
4321 rsurface.modelsvector3f_bufferoffset = 0;
4322 rsurface.modeltvector3f_bufferobject = 0;
4323 rsurface.modeltvector3f_bufferoffset = 0;
4324 rsurface.modelnormal3f_bufferobject = 0;
4325 rsurface.modelnormal3f_bufferoffset = 0;
4326 rsurface.generatedvertex = true;
4330 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4331 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4332 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4333 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4334 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4335 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4336 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4337 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4338 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4339 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4340 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4341 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4342 rsurface.generatedvertex = false;
4344 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4345 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4346 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4347 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4348 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4349 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4350 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4351 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4352 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4353 rsurface.modelelement3i = model->surfmesh.data_element3i;
4354 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4355 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4356 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4357 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4358 rsurface.modelsurfaces = model->data_surfaces;
4359 rsurface.vertex3f = rsurface.modelvertex3f;
4360 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4361 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4362 rsurface.svector3f = rsurface.modelsvector3f;
4363 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4364 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4365 rsurface.tvector3f = rsurface.modeltvector3f;
4366 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4367 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4368 rsurface.normal3f = rsurface.modelnormal3f;
4369 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4370 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4371 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4374 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4375 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4378 int texturesurfaceindex;
4383 const float *v1, *in_tc;
4385 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4387 q3shaderinfo_deform_t *deform;
4388 // 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
4389 if (rsurface.generatedvertex)
4391 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4392 generatenormals = true;
4393 for (i = 0;i < Q3MAXDEFORMS;i++)
4395 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4397 generatetangents = true;
4398 generatenormals = true;
4400 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4401 generatenormals = true;
4403 if (generatenormals && !rsurface.modelnormal3f)
4405 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4406 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4407 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4408 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4410 if (generatetangents && !rsurface.modelsvector3f)
4412 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4413 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4414 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4415 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4416 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4417 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4418 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);
4421 rsurface.vertex3f = rsurface.modelvertex3f;
4422 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4423 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4424 rsurface.svector3f = rsurface.modelsvector3f;
4425 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4426 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4427 rsurface.tvector3f = rsurface.modeltvector3f;
4428 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4429 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4430 rsurface.normal3f = rsurface.modelnormal3f;
4431 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4432 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4433 // if vertices are deformed (sprite flares and things in maps, possibly
4434 // water waves, bulges and other deformations), generate them into
4435 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4436 // (may be static model data or generated data for an animated model, or
4437 // the previous deform pass)
4438 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4440 switch (deform->deform)
4443 case Q3DEFORM_PROJECTIONSHADOW:
4444 case Q3DEFORM_TEXT0:
4445 case Q3DEFORM_TEXT1:
4446 case Q3DEFORM_TEXT2:
4447 case Q3DEFORM_TEXT3:
4448 case Q3DEFORM_TEXT4:
4449 case Q3DEFORM_TEXT5:
4450 case Q3DEFORM_TEXT6:
4451 case Q3DEFORM_TEXT7:
4454 case Q3DEFORM_AUTOSPRITE:
4455 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4456 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4457 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4458 VectorNormalize(newforward);
4459 VectorNormalize(newright);
4460 VectorNormalize(newup);
4461 // make deformed versions of only the model vertices used by the specified surfaces
4462 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4464 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4465 // a single autosprite surface can contain multiple sprites...
4466 for (j = 0;j < surface->num_vertices - 3;j += 4)
4468 VectorClear(center);
4469 for (i = 0;i < 4;i++)
4470 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4471 VectorScale(center, 0.25f, center);
4472 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4473 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4474 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4475 for (i = 0;i < 4;i++)
4477 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4478 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4481 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);
4482 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);
4484 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4485 rsurface.vertex3f_bufferobject = 0;
4486 rsurface.vertex3f_bufferoffset = 0;
4487 rsurface.svector3f = rsurface.array_deformedsvector3f;
4488 rsurface.svector3f_bufferobject = 0;
4489 rsurface.svector3f_bufferoffset = 0;
4490 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4491 rsurface.tvector3f_bufferobject = 0;
4492 rsurface.tvector3f_bufferoffset = 0;
4493 rsurface.normal3f = rsurface.array_deformednormal3f;
4494 rsurface.normal3f_bufferobject = 0;
4495 rsurface.normal3f_bufferoffset = 0;
4497 case Q3DEFORM_AUTOSPRITE2:
4498 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4499 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4500 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4501 VectorNormalize(newforward);
4502 VectorNormalize(newright);
4503 VectorNormalize(newup);
4504 // make deformed versions of only the model vertices used by the specified surfaces
4505 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4507 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4508 const float *v1, *v2;
4518 memset(shortest, 0, sizeof(shortest));
4519 // a single autosprite surface can contain multiple sprites...
4520 for (j = 0;j < surface->num_vertices - 3;j += 4)
4522 VectorClear(center);
4523 for (i = 0;i < 4;i++)
4524 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4525 VectorScale(center, 0.25f, center);
4526 // find the two shortest edges, then use them to define the
4527 // axis vectors for rotating around the central axis
4528 for (i = 0;i < 6;i++)
4530 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4531 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4533 Debug_PolygonBegin(NULL, 0, false, 0);
4534 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4535 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);
4536 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4539 l = VectorDistance2(v1, v2);
4540 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4542 l += (1.0f / 1024.0f);
4543 if (shortest[0].length2 > l || i == 0)
4545 shortest[1] = shortest[0];
4546 shortest[0].length2 = l;
4547 shortest[0].v1 = v1;
4548 shortest[0].v2 = v2;
4550 else if (shortest[1].length2 > l || i == 1)
4552 shortest[1].length2 = l;
4553 shortest[1].v1 = v1;
4554 shortest[1].v2 = v2;
4557 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4558 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4560 Debug_PolygonBegin(NULL, 0, false, 0);
4561 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4562 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);
4563 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4566 // this calculates the right vector from the shortest edge
4567 // and the up vector from the edge midpoints
4568 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4569 VectorNormalize(right);
4570 VectorSubtract(end, start, up);
4571 VectorNormalize(up);
4572 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4573 //VectorSubtract(rsurface.modelorg, center, forward);
4574 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4575 VectorNegate(forward, forward);
4576 VectorReflect(forward, 0, up, forward);
4577 VectorNormalize(forward);
4578 CrossProduct(up, forward, newright);
4579 VectorNormalize(newright);
4581 Debug_PolygonBegin(NULL, 0, false, 0);
4582 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);
4583 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4584 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4588 Debug_PolygonBegin(NULL, 0, false, 0);
4589 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4590 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4591 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4594 // rotate the quad around the up axis vector, this is made
4595 // especially easy by the fact we know the quad is flat,
4596 // so we only have to subtract the center position and
4597 // measure distance along the right vector, and then
4598 // multiply that by the newright vector and add back the
4600 // we also need to subtract the old position to undo the
4601 // displacement from the center, which we do with a
4602 // DotProduct, the subtraction/addition of center is also
4603 // optimized into DotProducts here
4604 l = DotProduct(right, center);
4605 for (i = 0;i < 4;i++)
4607 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4608 f = DotProduct(right, v1) - l;
4609 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4612 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);
4613 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);
4615 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4616 rsurface.vertex3f_bufferobject = 0;
4617 rsurface.vertex3f_bufferoffset = 0;
4618 rsurface.svector3f = rsurface.array_deformedsvector3f;
4619 rsurface.svector3f_bufferobject = 0;
4620 rsurface.svector3f_bufferoffset = 0;
4621 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4622 rsurface.tvector3f_bufferobject = 0;
4623 rsurface.tvector3f_bufferoffset = 0;
4624 rsurface.normal3f = rsurface.array_deformednormal3f;
4625 rsurface.normal3f_bufferobject = 0;
4626 rsurface.normal3f_bufferoffset = 0;
4628 case Q3DEFORM_NORMAL:
4629 // deform the normals to make reflections wavey
4630 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4632 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4633 for (j = 0;j < surface->num_vertices;j++)
4636 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4637 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4638 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4639 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4640 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4641 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4642 VectorNormalize(normal);
4644 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);
4646 rsurface.svector3f = rsurface.array_deformedsvector3f;
4647 rsurface.svector3f_bufferobject = 0;
4648 rsurface.svector3f_bufferoffset = 0;
4649 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4650 rsurface.tvector3f_bufferobject = 0;
4651 rsurface.tvector3f_bufferoffset = 0;
4652 rsurface.normal3f = rsurface.array_deformednormal3f;
4653 rsurface.normal3f_bufferobject = 0;
4654 rsurface.normal3f_bufferoffset = 0;
4657 // deform vertex array to make wavey water and flags and such
4658 waveparms[0] = deform->waveparms[0];
4659 waveparms[1] = deform->waveparms[1];
4660 waveparms[2] = deform->waveparms[2];
4661 waveparms[3] = deform->waveparms[3];
4662 // this is how a divisor of vertex influence on deformation
4663 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4664 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4665 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4667 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4668 for (j = 0;j < surface->num_vertices;j++)
4670 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4671 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4672 // if the wavefunc depends on time, evaluate it per-vertex
4675 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4676 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4678 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4681 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4682 rsurface.vertex3f_bufferobject = 0;
4683 rsurface.vertex3f_bufferoffset = 0;
4685 case Q3DEFORM_BULGE:
4686 // deform vertex array to make the surface have moving bulges
4687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4689 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4690 for (j = 0;j < surface->num_vertices;j++)
4692 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4693 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4696 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4697 rsurface.vertex3f_bufferobject = 0;
4698 rsurface.vertex3f_bufferoffset = 0;
4701 // deform vertex array
4702 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4703 VectorScale(deform->parms, scale, waveparms);
4704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4706 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4707 for (j = 0;j < surface->num_vertices;j++)
4708 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4710 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4711 rsurface.vertex3f_bufferobject = 0;
4712 rsurface.vertex3f_bufferoffset = 0;
4716 // generate texcoords based on the chosen texcoord source
4717 switch(rsurface.texture->tcgen.tcgen)
4720 case Q3TCGEN_TEXTURE:
4721 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4722 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4723 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4725 case Q3TCGEN_LIGHTMAP:
4726 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4727 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4728 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4730 case Q3TCGEN_VECTOR:
4731 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4733 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4734 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)
4736 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4737 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4740 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4741 rsurface.texcoordtexture2f_bufferobject = 0;
4742 rsurface.texcoordtexture2f_bufferoffset = 0;
4744 case Q3TCGEN_ENVIRONMENT:
4745 // make environment reflections using a spheremap
4746 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4748 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4749 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4750 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4751 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4752 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4754 float l, d, eyedir[3];
4755 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4756 l = 0.5f / VectorLength(eyedir);
4757 d = DotProduct(normal, eyedir)*2;
4758 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4759 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4762 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4763 rsurface.texcoordtexture2f_bufferobject = 0;
4764 rsurface.texcoordtexture2f_bufferoffset = 0;
4767 // the only tcmod that needs software vertex processing is turbulent, so
4768 // check for it here and apply the changes if needed
4769 // and we only support that as the first one
4770 // (handling a mixture of turbulent and other tcmods would be problematic
4771 // without punting it entirely to a software path)
4772 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4774 amplitude = rsurface.texture->tcmods[0].parms[1];
4775 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4776 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4778 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4779 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)
4781 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4782 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4785 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4786 rsurface.texcoordtexture2f_bufferobject = 0;
4787 rsurface.texcoordtexture2f_bufferoffset = 0;
4789 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4790 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4791 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4792 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4795 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4798 const msurface_t *surface = texturesurfacelist[0];
4799 const msurface_t *surface2;
4804 // TODO: lock all array ranges before render, rather than on each surface
4805 if (texturenumsurfaces == 1)
4807 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4808 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));
4810 else if (r_batchmode.integer == 2)
4812 #define MAXBATCHTRIANGLES 4096
4813 int batchtriangles = 0;
4814 int batchelements[MAXBATCHTRIANGLES*3];
4815 for (i = 0;i < texturenumsurfaces;i = j)
4817 surface = texturesurfacelist[i];
4819 if (surface->num_triangles > MAXBATCHTRIANGLES)
4821 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));
4824 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4825 batchtriangles = surface->num_triangles;
4826 firstvertex = surface->num_firstvertex;
4827 endvertex = surface->num_firstvertex + surface->num_vertices;
4828 for (;j < texturenumsurfaces;j++)
4830 surface2 = texturesurfacelist[j];
4831 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4833 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4834 batchtriangles += surface2->num_triangles;
4835 firstvertex = min(firstvertex, surface2->num_firstvertex);
4836 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4838 surface2 = texturesurfacelist[j-1];
4839 numvertices = endvertex - firstvertex;
4840 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4843 else if (r_batchmode.integer == 1)
4845 for (i = 0;i < texturenumsurfaces;i = j)
4847 surface = texturesurfacelist[i];
4848 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4849 if (texturesurfacelist[j] != surface2)
4851 surface2 = texturesurfacelist[j-1];
4852 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4853 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4854 GL_LockArrays(surface->num_firstvertex, numvertices);
4855 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4860 for (i = 0;i < texturenumsurfaces;i++)
4862 surface = texturesurfacelist[i];
4863 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4864 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));
4869 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4871 int i, planeindex, vertexindex;
4875 r_waterstate_waterplane_t *p, *bestp;
4876 msurface_t *surface;
4877 if (r_waterstate.renderingscene)
4879 for (i = 0;i < texturenumsurfaces;i++)
4881 surface = texturesurfacelist[i];
4882 if (lightmaptexunit >= 0)
4883 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4884 if (deluxemaptexunit >= 0)
4885 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4886 // pick the closest matching water plane
4889 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4892 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4894 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4895 d += fabs(PlaneDiff(vert, &p->plane));
4897 if (bestd > d || !bestp)
4905 if (refractiontexunit >= 0)
4906 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4907 if (reflectiontexunit >= 0)
4908 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4912 if (refractiontexunit >= 0)
4913 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4914 if (reflectiontexunit >= 0)
4915 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4917 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4918 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));
4922 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4926 const msurface_t *surface = texturesurfacelist[0];
4927 const msurface_t *surface2;
4932 // TODO: lock all array ranges before render, rather than on each surface
4933 if (texturenumsurfaces == 1)
4935 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4936 if (deluxemaptexunit >= 0)
4937 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4938 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4939 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));
4941 else if (r_batchmode.integer == 2)
4943 #define MAXBATCHTRIANGLES 4096
4944 int batchtriangles = 0;
4945 int batchelements[MAXBATCHTRIANGLES*3];
4946 for (i = 0;i < texturenumsurfaces;i = j)
4948 surface = texturesurfacelist[i];
4949 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4950 if (deluxemaptexunit >= 0)
4951 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4953 if (surface->num_triangles > MAXBATCHTRIANGLES)
4955 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));
4958 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4959 batchtriangles = surface->num_triangles;
4960 firstvertex = surface->num_firstvertex;
4961 endvertex = surface->num_firstvertex + surface->num_vertices;
4962 for (;j < texturenumsurfaces;j++)
4964 surface2 = texturesurfacelist[j];
4965 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4967 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4968 batchtriangles += surface2->num_triangles;
4969 firstvertex = min(firstvertex, surface2->num_firstvertex);
4970 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4972 surface2 = texturesurfacelist[j-1];
4973 numvertices = endvertex - firstvertex;
4974 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4977 else if (r_batchmode.integer == 1)
4980 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4981 for (i = 0;i < texturenumsurfaces;i = j)
4983 surface = texturesurfacelist[i];
4984 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4985 if (texturesurfacelist[j] != surface2)
4987 Con_Printf(" %i", j - i);
4990 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4992 for (i = 0;i < texturenumsurfaces;i = j)
4994 surface = texturesurfacelist[i];
4995 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4996 if (deluxemaptexunit >= 0)
4997 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4998 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4999 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5002 Con_Printf(" %i", j - i);
5004 surface2 = texturesurfacelist[j-1];
5005 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5006 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5007 GL_LockArrays(surface->num_firstvertex, numvertices);
5008 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5016 for (i = 0;i < texturenumsurfaces;i++)
5018 surface = texturesurfacelist[i];
5019 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5020 if (deluxemaptexunit >= 0)
5021 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5022 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5023 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));
5028 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5031 int texturesurfaceindex;
5032 if (r_showsurfaces.integer == 2)
5034 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5036 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5037 for (j = 0;j < surface->num_triangles;j++)
5039 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5040 GL_Color(f, f, f, 1);
5041 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)));
5047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5050 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5051 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);
5052 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5053 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));
5058 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5060 int texturesurfaceindex;
5064 if (rsurface.lightmapcolor4f)
5066 // generate color arrays for the surfaces in this list
5067 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5069 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5070 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)
5072 f = FogPoint_Model(v);
5082 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5084 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5085 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)
5087 f = FogPoint_Model(v);
5095 rsurface.lightmapcolor4f = rsurface.array_color4f;
5096 rsurface.lightmapcolor4f_bufferobject = 0;
5097 rsurface.lightmapcolor4f_bufferoffset = 0;
5100 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5102 int texturesurfaceindex;
5105 if (!rsurface.lightmapcolor4f)
5107 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5109 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5110 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)
5118 rsurface.lightmapcolor4f = rsurface.array_color4f;
5119 rsurface.lightmapcolor4f_bufferobject = 0;
5120 rsurface.lightmapcolor4f_bufferoffset = 0;
5123 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5126 rsurface.lightmapcolor4f = NULL;
5127 rsurface.lightmapcolor4f_bufferobject = 0;
5128 rsurface.lightmapcolor4f_bufferoffset = 0;
5129 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5130 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5131 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5132 GL_Color(r, g, b, a);
5133 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5136 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5138 // TODO: optimize applyfog && applycolor case
5139 // just apply fog if necessary, and tint the fog color array if necessary
5140 rsurface.lightmapcolor4f = NULL;
5141 rsurface.lightmapcolor4f_bufferobject = 0;
5142 rsurface.lightmapcolor4f_bufferoffset = 0;
5143 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5144 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5145 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5146 GL_Color(r, g, b, a);
5147 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5150 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5152 int texturesurfaceindex;
5156 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5158 // generate color arrays for the surfaces in this list
5159 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5161 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5162 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5164 if (surface->lightmapinfo->samples)
5166 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5167 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5168 VectorScale(lm, scale, c);
5169 if (surface->lightmapinfo->styles[1] != 255)
5171 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5173 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5174 VectorMA(c, scale, lm, c);
5175 if (surface->lightmapinfo->styles[2] != 255)
5178 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5179 VectorMA(c, scale, lm, c);
5180 if (surface->lightmapinfo->styles[3] != 255)
5183 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5184 VectorMA(c, scale, lm, c);
5194 rsurface.lightmapcolor4f = rsurface.array_color4f;
5195 rsurface.lightmapcolor4f_bufferobject = 0;
5196 rsurface.lightmapcolor4f_bufferoffset = 0;
5200 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5201 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5202 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5204 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5205 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5206 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5207 GL_Color(r, g, b, a);
5208 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5211 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5213 int texturesurfaceindex;
5217 vec3_t ambientcolor;
5218 vec3_t diffusecolor;
5222 VectorCopy(rsurface.modellight_lightdir, lightdir);
5223 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5224 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5225 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5226 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5227 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5228 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5229 if (VectorLength2(diffusecolor) > 0)
5231 // generate color arrays for the surfaces in this list
5232 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5234 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5235 int numverts = surface->num_vertices;
5236 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5237 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5238 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5239 // q3-style directional shading
5240 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5242 if ((f = DotProduct(c2, lightdir)) > 0)
5243 VectorMA(ambientcolor, f, diffusecolor, c);
5245 VectorCopy(ambientcolor, c);
5254 rsurface.lightmapcolor4f = rsurface.array_color4f;
5255 rsurface.lightmapcolor4f_bufferobject = 0;
5256 rsurface.lightmapcolor4f_bufferoffset = 0;
5260 r = ambientcolor[0];
5261 g = ambientcolor[1];
5262 b = ambientcolor[2];
5263 rsurface.lightmapcolor4f = NULL;
5264 rsurface.lightmapcolor4f_bufferobject = 0;
5265 rsurface.lightmapcolor4f_bufferoffset = 0;
5267 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5268 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5269 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5270 GL_Color(r, g, b, a);
5271 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5274 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5276 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5277 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5278 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5279 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5280 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5282 rsurface.mode = RSURFMODE_SHOWSURFACES;
5284 GL_BlendFunc(GL_ONE, GL_ZERO);
5285 R_Mesh_ColorPointer(NULL, 0, 0);
5286 R_Mesh_ResetTextureState();
5288 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5289 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5292 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5294 // transparent sky would be ridiculous
5295 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5297 if (rsurface.mode != RSURFMODE_SKY)
5299 if (rsurface.mode == RSURFMODE_GLSL)
5301 qglUseProgramObjectARB(0);CHECKGLERROR
5303 rsurface.mode = RSURFMODE_SKY;
5307 skyrendernow = false;
5309 // restore entity matrix
5310 R_Mesh_Matrix(&rsurface.matrix);
5312 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5313 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5314 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5315 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5317 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5318 // skymasking on them, and Quake3 never did sky masking (unlike
5319 // software Quake and software Quake2), so disable the sky masking
5320 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5321 // and skymasking also looks very bad when noclipping outside the
5322 // level, so don't use it then either.
5323 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5325 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5326 R_Mesh_ColorPointer(NULL, 0, 0);
5327 R_Mesh_ResetTextureState();
5328 if (skyrendermasked)
5330 // depth-only (masking)
5331 GL_ColorMask(0,0,0,0);
5332 // just to make sure that braindead drivers don't draw
5333 // anything despite that colormask...
5334 GL_BlendFunc(GL_ZERO, GL_ONE);
5339 GL_BlendFunc(GL_ONE, GL_ZERO);
5341 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5342 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5343 if (skyrendermasked)
5344 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5348 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5350 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5353 if (rsurface.mode != RSURFMODE_GLSL)
5355 rsurface.mode = RSURFMODE_GLSL;
5356 R_Mesh_ResetTextureState();
5359 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5360 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5361 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5362 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5363 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5364 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5365 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5368 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5369 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5370 R_Mesh_ColorPointer(NULL, 0, 0);
5372 else if (rsurface.uselightmaptexture)
5374 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5375 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5376 R_Mesh_ColorPointer(NULL, 0, 0);
5380 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5381 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5382 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5384 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5385 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5386 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5388 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5390 // render background
5391 GL_BlendFunc(GL_ONE, GL_ZERO);
5393 GL_AlphaTest(false);
5395 GL_Color(1, 1, 1, 1);
5396 R_Mesh_ColorPointer(NULL, 0, 0);
5398 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5399 if (r_glsl_permutation)
5401 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5402 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5403 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5404 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5405 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5406 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5407 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5410 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5411 GL_DepthMask(false);
5412 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5413 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5415 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5416 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5417 R_Mesh_ColorPointer(NULL, 0, 0);
5419 else if (rsurface.uselightmaptexture)
5421 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5422 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5423 R_Mesh_ColorPointer(NULL, 0, 0);
5427 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5428 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5429 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5431 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5432 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5435 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5436 if (!r_glsl_permutation)
5439 if (rsurface.lightmode == 2)
5440 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5442 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5443 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5444 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5445 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5446 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5447 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5448 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]);
5450 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5452 GL_BlendFunc(GL_ONE, GL_ZERO);
5454 GL_AlphaTest(false);
5457 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5459 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5460 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5462 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5466 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5467 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5469 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5471 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5476 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5478 // OpenGL 1.3 path - anything not completely ancient
5479 int texturesurfaceindex;
5480 qboolean applycolor;
5484 const texturelayer_t *layer;
5485 if (rsurface.mode != RSURFMODE_MULTIPASS)
5486 rsurface.mode = RSURFMODE_MULTIPASS;
5487 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5489 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5492 int layertexrgbscale;
5493 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5495 if (layerindex == 0)
5499 GL_AlphaTest(false);
5500 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5503 GL_DepthMask(layer->depthmask);
5504 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5505 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5507 layertexrgbscale = 4;
5508 VectorScale(layer->color, 0.25f, layercolor);
5510 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5512 layertexrgbscale = 2;
5513 VectorScale(layer->color, 0.5f, layercolor);
5517 layertexrgbscale = 1;
5518 VectorScale(layer->color, 1.0f, layercolor);
5520 layercolor[3] = layer->color[3];
5521 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5522 R_Mesh_ColorPointer(NULL, 0, 0);
5523 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5524 switch (layer->type)
5526 case TEXTURELAYERTYPE_LITTEXTURE:
5527 memset(&m, 0, sizeof(m));
5528 m.tex[0] = R_GetTexture(r_texture_white);
5529 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5530 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5531 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5532 m.tex[1] = R_GetTexture(layer->texture);
5533 m.texmatrix[1] = layer->texmatrix;
5534 m.texrgbscale[1] = layertexrgbscale;
5535 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5536 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5537 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5538 R_Mesh_TextureState(&m);
5539 if (rsurface.lightmode == 2)
5540 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5541 else if (rsurface.uselightmaptexture)
5542 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5544 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5546 case TEXTURELAYERTYPE_TEXTURE:
5547 memset(&m, 0, sizeof(m));
5548 m.tex[0] = R_GetTexture(layer->texture);
5549 m.texmatrix[0] = layer->texmatrix;
5550 m.texrgbscale[0] = layertexrgbscale;
5551 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5552 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5553 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5554 R_Mesh_TextureState(&m);
5555 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5557 case TEXTURELAYERTYPE_FOG:
5558 memset(&m, 0, sizeof(m));
5559 m.texrgbscale[0] = layertexrgbscale;
5562 m.tex[0] = R_GetTexture(layer->texture);
5563 m.texmatrix[0] = layer->texmatrix;
5564 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5565 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5566 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5568 R_Mesh_TextureState(&m);
5569 // generate a color array for the fog pass
5570 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5571 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5575 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5576 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)
5578 f = 1 - FogPoint_Model(v);
5579 c[0] = layercolor[0];
5580 c[1] = layercolor[1];
5581 c[2] = layercolor[2];
5582 c[3] = f * layercolor[3];
5585 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5588 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5590 GL_LockArrays(0, 0);
5593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5595 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5596 GL_AlphaTest(false);
5600 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5602 // OpenGL 1.1 - crusty old voodoo path
5603 int texturesurfaceindex;
5607 const texturelayer_t *layer;
5608 if (rsurface.mode != RSURFMODE_MULTIPASS)
5609 rsurface.mode = RSURFMODE_MULTIPASS;
5610 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5612 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5614 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5616 if (layerindex == 0)
5620 GL_AlphaTest(false);
5621 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5624 GL_DepthMask(layer->depthmask);
5625 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5626 R_Mesh_ColorPointer(NULL, 0, 0);
5627 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5628 switch (layer->type)
5630 case TEXTURELAYERTYPE_LITTEXTURE:
5631 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5633 // two-pass lit texture with 2x rgbscale
5634 // first the lightmap pass
5635 memset(&m, 0, sizeof(m));
5636 m.tex[0] = R_GetTexture(r_texture_white);
5637 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5638 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5639 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5640 R_Mesh_TextureState(&m);
5641 if (rsurface.lightmode == 2)
5642 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5643 else if (rsurface.uselightmaptexture)
5644 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5646 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5647 GL_LockArrays(0, 0);
5648 // then apply the texture to it
5649 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5650 memset(&m, 0, sizeof(m));
5651 m.tex[0] = R_GetTexture(layer->texture);
5652 m.texmatrix[0] = layer->texmatrix;
5653 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5654 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5655 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5656 R_Mesh_TextureState(&m);
5657 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);
5661 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5662 memset(&m, 0, sizeof(m));
5663 m.tex[0] = R_GetTexture(layer->texture);
5664 m.texmatrix[0] = layer->texmatrix;
5665 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5666 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5667 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5668 R_Mesh_TextureState(&m);
5669 if (rsurface.lightmode == 2)
5670 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);
5672 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);
5675 case TEXTURELAYERTYPE_TEXTURE:
5676 // singletexture unlit texture with transparency support
5677 memset(&m, 0, sizeof(m));
5678 m.tex[0] = R_GetTexture(layer->texture);
5679 m.texmatrix[0] = layer->texmatrix;
5680 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5681 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5682 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5683 R_Mesh_TextureState(&m);
5684 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);
5686 case TEXTURELAYERTYPE_FOG:
5687 // singletexture fogging
5688 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5691 memset(&m, 0, sizeof(m));
5692 m.tex[0] = R_GetTexture(layer->texture);
5693 m.texmatrix[0] = layer->texmatrix;
5694 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5695 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5696 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5697 R_Mesh_TextureState(&m);
5700 R_Mesh_ResetTextureState();
5701 // generate a color array for the fog pass
5702 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5706 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5707 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)
5709 f = 1 - FogPoint_Model(v);
5710 c[0] = layer->color[0];
5711 c[1] = layer->color[1];
5712 c[2] = layer->color[2];
5713 c[3] = f * layer->color[3];
5716 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5719 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5721 GL_LockArrays(0, 0);
5724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5726 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5727 GL_AlphaTest(false);
5731 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5733 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5735 rsurface.rtlight = NULL;
5739 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5741 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5743 if (rsurface.mode != RSURFMODE_MULTIPASS)
5744 rsurface.mode = RSURFMODE_MULTIPASS;
5745 if (r_depthfirst.integer == 3)
5747 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5748 if (!r_view.showdebug)
5749 GL_Color(0, 0, 0, 1);
5751 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5755 GL_ColorMask(0,0,0,0);
5758 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5759 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5760 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5762 GL_BlendFunc(GL_ONE, GL_ZERO);
5764 GL_AlphaTest(false);
5765 R_Mesh_ColorPointer(NULL, 0, 0);
5766 R_Mesh_ResetTextureState();
5767 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5768 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5769 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5770 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5772 else if (r_depthfirst.integer == 3)
5774 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5776 GL_Color(0, 0, 0, 1);
5777 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5779 else if (r_showsurfaces.integer)
5781 if (rsurface.mode != RSURFMODE_MULTIPASS)
5782 rsurface.mode = RSURFMODE_MULTIPASS;
5783 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5784 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5786 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5787 GL_BlendFunc(GL_ONE, GL_ZERO);
5788 GL_DepthMask(writedepth);
5790 GL_AlphaTest(false);
5791 R_Mesh_ColorPointer(NULL, 0, 0);
5792 R_Mesh_ResetTextureState();
5793 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5794 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5795 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5797 else if (gl_lightmaps.integer)
5800 if (rsurface.mode != RSURFMODE_MULTIPASS)
5801 rsurface.mode = RSURFMODE_MULTIPASS;
5802 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5804 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5805 GL_BlendFunc(GL_ONE, GL_ZERO);
5806 GL_DepthMask(writedepth);
5808 GL_AlphaTest(false);
5809 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5810 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5811 R_Mesh_ColorPointer(NULL, 0, 0);
5812 memset(&m, 0, sizeof(m));
5813 m.tex[0] = R_GetTexture(r_texture_white);
5814 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5815 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5816 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5817 R_Mesh_TextureState(&m);
5818 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5819 if (rsurface.lightmode == 2)
5820 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5821 else if (rsurface.uselightmaptexture)
5822 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5824 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5825 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5827 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5829 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5830 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5832 else if (rsurface.texture->currentnumlayers)
5834 // write depth for anything we skipped on the depth-only pass earlier
5835 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5837 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5838 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5839 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5840 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5841 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5842 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5843 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5844 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5845 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5846 if (r_glsl.integer && gl_support_fragment_shader)
5847 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5848 else if (gl_combine.integer && r_textureunits.integer >= 2)
5849 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5851 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5852 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5855 GL_LockArrays(0, 0);
5858 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5861 int texturenumsurfaces, endsurface;
5863 msurface_t *surface;
5864 msurface_t *texturesurfacelist[1024];
5866 // if the model is static it doesn't matter what value we give for
5867 // wantnormals and wanttangents, so this logic uses only rules applicable
5868 // to a model, knowing that they are meaningless otherwise
5869 if (ent == r_refdef.worldentity)
5870 RSurf_ActiveWorldEntity();
5871 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5872 RSurf_ActiveModelEntity(ent, false, false);
5874 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5876 for (i = 0;i < numsurfaces;i = j)
5879 surface = rsurface.modelsurfaces + surfacelist[i];
5880 texture = surface->texture;
5881 R_UpdateTextureInfo(ent, texture);
5882 rsurface.texture = texture->currentframe;
5883 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5884 // scan ahead until we find a different texture
5885 endsurface = min(i + 1024, numsurfaces);
5886 texturenumsurfaces = 0;
5887 texturesurfacelist[texturenumsurfaces++] = surface;
5888 for (;j < endsurface;j++)
5890 surface = rsurface.modelsurfaces + surfacelist[j];
5891 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5893 texturesurfacelist[texturenumsurfaces++] = surface;
5895 // render the range of surfaces
5896 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5902 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5905 vec3_t tempcenter, center;
5907 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5910 for (i = 0;i < numsurfaces;i++)
5911 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5912 R_Water_AddWaterPlane(surfacelist[i]);
5915 // break the surface list down into batches by texture and use of lightmapping
5916 for (i = 0;i < numsurfaces;i = j)
5919 // texture is the base texture pointer, rsurface.texture is the
5920 // current frame/skin the texture is directing us to use (for example
5921 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5922 // use skin 1 instead)
5923 texture = surfacelist[i]->texture;
5924 rsurface.texture = texture->currentframe;
5925 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5926 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5928 // if this texture is not the kind we want, skip ahead to the next one
5929 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5933 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5935 // transparent surfaces get pushed off into the transparent queue
5936 const msurface_t *surface = surfacelist[i];
5939 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5940 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5941 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5942 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5943 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5947 // simply scan ahead until we find a different texture or lightmap state
5948 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5950 // render the range of surfaces
5951 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5956 float locboxvertex3f[6*4*3] =
5958 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5959 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5960 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5961 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5962 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5963 1,0,0, 0,0,0, 0,1,0, 1,1,0
5966 int locboxelement3i[6*2*3] =
5976 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5979 cl_locnode_t *loc = (cl_locnode_t *)ent;
5981 float vertex3f[6*4*3];
5983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5984 GL_DepthMask(false);
5985 GL_DepthRange(0, 1);
5986 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5988 GL_CullFace(GL_NONE);
5989 R_Mesh_Matrix(&identitymatrix);
5991 R_Mesh_VertexPointer(vertex3f, 0, 0);
5992 R_Mesh_ColorPointer(NULL, 0, 0);
5993 R_Mesh_ResetTextureState();
5996 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5997 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5998 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5999 surfacelist[0] < 0 ? 0.5f : 0.125f);
6001 if (VectorCompare(loc->mins, loc->maxs))
6003 VectorSet(size, 2, 2, 2);
6004 VectorMA(loc->mins, -0.5f, size, mins);
6008 VectorCopy(loc->mins, mins);
6009 VectorSubtract(loc->maxs, loc->mins, size);
6012 for (i = 0;i < 6*4*3;)
6013 for (j = 0;j < 3;j++, i++)
6014 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6016 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6019 void R_DrawLocs(void)
6022 cl_locnode_t *loc, *nearestloc;
6024 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6025 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6027 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6028 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6032 void R_DrawDebugModel(entity_render_t *ent)
6034 int i, j, k, l, flagsmask;
6035 const int *elements;
6037 msurface_t *surface;
6038 model_t *model = ent->model;
6041 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6043 R_Mesh_ColorPointer(NULL, 0, 0);
6044 R_Mesh_ResetTextureState();
6045 GL_DepthRange(0, 1);
6046 GL_DepthTest(!r_showdisabledepthtest.integer);
6047 GL_DepthMask(false);
6048 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6050 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6052 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6053 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6055 if (brush->colbrushf && brush->colbrushf->numtriangles)
6057 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6058 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, r_showcollisionbrushes.value);
6059 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6062 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6064 if (surface->num_collisiontriangles)
6066 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6067 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, r_showcollisionbrushes.value);
6068 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6073 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6075 if (r_showtris.integer || r_shownormals.integer)
6077 if (r_showdisabledepthtest.integer)
6079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6080 GL_DepthMask(false);
6084 GL_BlendFunc(GL_ONE, GL_ZERO);
6087 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6089 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6091 rsurface.texture = surface->texture->currentframe;
6092 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6094 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6095 if (r_showtris.value > 0)
6097 if (!rsurface.texture->currentlayers->depthmask)
6098 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6099 else if (ent == r_refdef.worldentity)
6100 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6102 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6103 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6106 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6108 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6109 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6110 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6111 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6116 if (r_shownormals.value > 0)
6118 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6120 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6122 VectorCopy(rsurface.vertex3f + l * 3, v);
6123 qglVertex3f(v[0], v[1], v[2]);
6124 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6125 qglVertex3f(v[0], v[1], v[2]);
6129 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6131 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6133 VectorCopy(rsurface.vertex3f + l * 3, v);
6134 qglVertex3f(v[0], v[1], v[2]);
6135 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6136 qglVertex3f(v[0], v[1], v[2]);
6140 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6142 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6144 VectorCopy(rsurface.vertex3f + l * 3, v);
6145 qglVertex3f(v[0], v[1], v[2]);
6146 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6147 qglVertex3f(v[0], v[1], v[2]);
6154 rsurface.texture = NULL;
6158 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6159 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6161 int i, j, endj, f, flagsmask;
6162 int counttriangles = 0;
6163 msurface_t *surface, **surfacechain;
6165 model_t *model = r_refdef.worldmodel;
6166 const int maxsurfacelist = 1024;
6167 int numsurfacelist = 0;
6168 msurface_t *surfacelist[1024];
6172 RSurf_ActiveWorldEntity();
6174 // update light styles
6175 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6177 for (i = 0;i < model->brushq1.light_styles;i++)
6179 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6181 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6182 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6183 for (;(surface = *surfacechain);surfacechain++)
6184 surface->cached_dlight = true;
6189 R_UpdateAllTextureInfo(r_refdef.worldentity);
6190 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6194 R_DrawDebugModel(r_refdef.worldentity);
6200 rsurface.uselightmaptexture = false;
6201 rsurface.texture = NULL;
6203 j = model->firstmodelsurface;
6204 endj = j + model->nummodelsurfaces;
6207 // quickly skip over non-visible surfaces
6208 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6210 // quickly iterate over visible surfaces
6211 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6213 // process this surface
6214 surface = model->data_surfaces + j;
6215 // if this surface fits the criteria, add it to the list
6216 if (surface->num_triangles)
6218 // if lightmap parameters changed, rebuild lightmap texture
6219 if (surface->cached_dlight)
6220 R_BuildLightMap(r_refdef.worldentity, surface);
6221 // add face to draw list
6222 surfacelist[numsurfacelist++] = surface;
6223 counttriangles += surface->num_triangles;
6224 if (numsurfacelist >= maxsurfacelist)
6226 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6233 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6234 r_refdef.stats.entities_triangles += counttriangles;
6238 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6240 int i, f, flagsmask;
6241 int counttriangles = 0;
6242 msurface_t *surface, *endsurface, **surfacechain;
6244 model_t *model = ent->model;
6245 const int maxsurfacelist = 1024;
6246 int numsurfacelist = 0;
6247 msurface_t *surfacelist[1024];
6251 // if the model is static it doesn't matter what value we give for
6252 // wantnormals and wanttangents, so this logic uses only rules applicable
6253 // to a model, knowing that they are meaningless otherwise
6254 if (ent == r_refdef.worldentity)
6255 RSurf_ActiveWorldEntity();
6256 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6257 RSurf_ActiveModelEntity(ent, false, false);
6259 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6261 // update light styles
6262 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6264 for (i = 0;i < model->brushq1.light_styles;i++)
6266 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6268 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6269 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6270 for (;(surface = *surfacechain);surfacechain++)
6271 surface->cached_dlight = true;
6276 R_UpdateAllTextureInfo(ent);
6277 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6281 R_DrawDebugModel(ent);
6287 rsurface.uselightmaptexture = false;
6288 rsurface.texture = NULL;
6290 surface = model->data_surfaces + model->firstmodelsurface;
6291 endsurface = surface + model->nummodelsurfaces;
6292 for (;surface < endsurface;surface++)
6294 // if this surface fits the criteria, add it to the list
6295 if (surface->num_triangles)
6297 // if lightmap parameters changed, rebuild lightmap texture
6298 if (surface->cached_dlight)
6299 R_BuildLightMap(ent, surface);
6300 // add face to draw list
6301 surfacelist[numsurfacelist++] = surface;
6302 counttriangles += surface->num_triangles;
6303 if (numsurfacelist >= maxsurfacelist)
6305 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6311 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6312 r_refdef.stats.entities_triangles += counttriangles;