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_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
82 cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
83 cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
84 cvar_t r_glsl_water_refractcolor_r = {CVAR_SAVE, "r_glsl_water_refractcolor_r", "1", "water color tint for refraction"};
85 cvar_t r_glsl_water_refractcolor_g = {CVAR_SAVE, "r_glsl_water_refractcolor_g", "1", "water color tint for refraction"};
86 cvar_t r_glsl_water_refractcolor_b = {CVAR_SAVE, "r_glsl_water_refractcolor_b", "1", "water color tint for refraction"};
87 cvar_t r_glsl_water_reflectcolor_r = {CVAR_SAVE, "r_glsl_water_reflectcolor_r", "1", "water color tint for reflection"};
88 cvar_t r_glsl_water_reflectcolor_g = {CVAR_SAVE, "r_glsl_water_reflectcolor_g", "1", "water color tint for reflection"};
89 cvar_t r_glsl_water_reflectcolor_b = {CVAR_SAVE, "r_glsl_water_reflectcolor_b", "1", "water color tint for reflection"};
90 cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"};
92 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)"};
93 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)"};
95 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
96 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 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)"};
112 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"};
114 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"};
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
121 extern qboolean v_flipped_state;
123 typedef struct r_glsl_bloomshader_s
126 int loc_Texture_Bloom;
128 r_glsl_bloomshader_t;
130 static struct r_bloomstate_s
135 int bloomwidth, bloomheight;
137 int screentexturewidth, screentextureheight;
138 rtexture_t *texture_screen;
140 int bloomtexturewidth, bloomtextureheight;
141 rtexture_t *texture_bloom;
143 r_glsl_bloomshader_t *shader;
145 // arrays for rendering the screen passes
146 float screentexcoord2f[8];
147 float bloomtexcoord2f[8];
148 float offsettexcoord2f[8];
152 typedef struct r_waterstate_waterplane_s
154 rtexture_t *texture_refraction;
155 rtexture_t *texture_reflection;
158 r_waterstate_waterplane_t;
160 #define MAX_WATERPLANES 16
162 static struct r_waterstate_s
166 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
168 int waterwidth, waterheight;
169 int texturewidth, textureheight;
171 int maxwaterplanes; // same as MAX_WATERPLANES
173 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
175 float screenscale[2];
176 float screencenter[2];
180 // shadow volume bsp struct with automatically growing nodes buffer
183 rtexture_t *r_texture_blanknormalmap;
184 rtexture_t *r_texture_white;
185 rtexture_t *r_texture_grey128;
186 rtexture_t *r_texture_black;
187 rtexture_t *r_texture_notexture;
188 rtexture_t *r_texture_whitecube;
189 rtexture_t *r_texture_normalizationcube;
190 rtexture_t *r_texture_fogattenuation;
191 //rtexture_t *r_texture_fogintensity;
193 // information about each possible shader permutation
194 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
195 // currently selected permutation
196 r_glsl_permutation_t *r_glsl_permutation;
198 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
199 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
201 // vertex coordinates for a quad that covers the screen exactly
202 const static float r_screenvertex3f[12] =
210 extern void R_DrawModelShadows(void);
212 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
215 for (i = 0;i < verts;i++)
226 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
229 for (i = 0;i < verts;i++)
239 // FIXME: move this to client?
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_Set("gl_fogenable", "0");
245 Cvar_Set("gl_fogdensity", "0.2");
246 Cvar_Set("gl_fogred", "0.3");
247 Cvar_Set("gl_foggreen", "0.3");
248 Cvar_Set("gl_fogblue", "0.3");
250 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
253 float FogPoint_World(const vec3_t p)
255 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
256 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
259 float FogPoint_Model(const vec3_t p)
261 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
262 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
265 static void R_BuildBlankTextures(void)
267 unsigned char data[4];
268 data[0] = 128; // normal X
269 data[1] = 128; // normal Y
270 data[2] = 255; // normal Z
271 data[3] = 128; // height
272 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
277 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
282 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
287 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
290 static void R_BuildNoTexture(void)
293 unsigned char pix[16][16][4];
294 // this makes a light grey/dark grey checkerboard texture
295 for (y = 0;y < 16;y++)
297 for (x = 0;x < 16;x++)
299 if ((y < 8) ^ (x < 8))
315 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
318 static void R_BuildWhiteCube(void)
320 unsigned char data[6*1*1*4];
321 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
322 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
323 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
324 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
325 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
326 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
327 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
330 static void R_BuildNormalizationCube(void)
334 vec_t s, t, intensity;
336 unsigned char data[6][NORMSIZE][NORMSIZE][4];
337 for (side = 0;side < 6;side++)
339 for (y = 0;y < NORMSIZE;y++)
341 for (x = 0;x < NORMSIZE;x++)
343 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
344 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
379 intensity = 127.0f / sqrt(DotProduct(v, v));
380 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
381 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
382 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
383 data[side][y][x][3] = 255;
387 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
390 static void R_BuildFogTexture(void)
394 unsigned char data1[FOGWIDTH][4];
395 //unsigned char data2[FOGWIDTH][4];
396 for (x = 0;x < FOGWIDTH;x++)
398 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
403 //data2[x][0] = 255 - b;
404 //data2[x][1] = 255 - b;
405 //data2[x][2] = 255 - b;
408 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 static const char *builtinshaderstring =
413 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
414 "// written by Forest 'LordHavoc' Hale\n"
416 "// common definitions between vertex shader and fragment shader:\n"
418 "#ifdef __GLSL_CG_DATA_TYPES\n"
419 "#define myhalf half\n"
420 "#define myhvec2 hvec2\n"
421 "#define myhvec3 hvec3\n"
422 "#define myhvec4 hvec4\n"
424 "#define myhalf float\n"
425 "#define myhvec2 vec2\n"
426 "#define myhvec3 vec3\n"
427 "#define myhvec4 vec4\n"
430 "varying vec2 TexCoord;\n"
431 "varying vec2 TexCoordLightmap;\n"
433 "varying vec3 CubeVector;\n"
434 "varying vec3 LightVector;\n"
435 "varying vec3 EyeVector;\n"
437 "varying vec3 EyeVectorModelSpace;\n"
440 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
441 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
442 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
445 "varying vec4 ModelViewProjectionPosition;\n"
446 "//varying vec4 ModelViewProjectionPosition_svector;\n"
447 "//varying vec4 ModelViewProjectionPosition_tvector;\n"
453 "// vertex shader specific:\n"
454 "#ifdef VERTEX_SHADER\n"
456 "uniform vec3 LightPosition;\n"
457 "uniform vec3 EyePosition;\n"
458 "uniform vec3 LightDir;\n"
460 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
464 " gl_FrontColor = gl_Color;\n"
465 " // copy the surface texcoord\n"
466 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
467 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
468 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
471 "#ifdef MODE_LIGHTSOURCE\n"
472 " // transform vertex position into light attenuation/cubemap space\n"
473 " // (-1 to +1 across the light box)\n"
474 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
476 " // transform unnormalized light direction into tangent space\n"
477 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
478 " // normalize it per pixel)\n"
479 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
480 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
481 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
482 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
485 "#ifdef MODE_LIGHTDIRECTION\n"
486 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
487 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
488 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
491 " // transform unnormalized eye direction into tangent space\n"
493 " vec3 EyeVectorModelSpace;\n"
495 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
496 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
497 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
498 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
500 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
501 " VectorS = gl_MultiTexCoord1.xyz;\n"
502 " VectorT = gl_MultiTexCoord2.xyz;\n"
503 " VectorR = gl_MultiTexCoord3.xyz;\n"
506 "//#ifdef USEWATER\n"
507 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
508 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
509 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
512 "// transform vertex to camera space, using ftransform to match non-VS\n"
514 " gl_Position = ftransform();\n"
516 " ModelViewProjectionPosition = gl_Position;\n"
520 "#endif // VERTEX_SHADER\n"
525 "// fragment shader specific:\n"
526 "#ifdef FRAGMENT_SHADER\n"
528 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
529 "uniform sampler2D Texture_Normal;\n"
530 "uniform sampler2D Texture_Color;\n"
531 "uniform sampler2D Texture_Gloss;\n"
532 "uniform samplerCube Texture_Cube;\n"
533 "uniform sampler2D Texture_Attenuation;\n"
534 "uniform sampler2D Texture_FogMask;\n"
535 "uniform sampler2D Texture_Pants;\n"
536 "uniform sampler2D Texture_Shirt;\n"
537 "uniform sampler2D Texture_Lightmap;\n"
538 "uniform sampler2D Texture_Deluxemap;\n"
539 "uniform sampler2D Texture_Glow;\n"
540 "uniform sampler2D Texture_Reflection;\n"
541 "uniform sampler2D Texture_Refraction;\n"
543 "uniform myhvec3 LightColor;\n"
544 "uniform myhvec3 AmbientColor;\n"
545 "uniform myhvec3 DiffuseColor;\n"
546 "uniform myhvec3 SpecularColor;\n"
547 "uniform myhvec3 Color_Pants;\n"
548 "uniform myhvec3 Color_Shirt;\n"
549 "uniform myhvec3 FogColor;\n"
552 "uniform vec4 DistortScaleRefractReflect;\n"
553 "uniform vec4 ScreenScaleRefractReflect;\n"
554 "uniform vec4 ScreenCenterRefractReflect;\n"
555 "uniform myhvec3 RefractColor;\n"
556 "uniform myhvec3 ReflectColor;\n"
559 "uniform myhalf GlowScale;\n"
560 "uniform myhalf SceneBrightness;\n"
561 "#ifdef USECONTRASTBOOST\n"
562 "uniform myhalf ContrastBoostCoeff;\n"
565 "uniform float OffsetMapping_Scale;\n"
566 "uniform float OffsetMapping_Bias;\n"
567 "uniform float FogRangeRecip;\n"
569 "uniform myhalf AmbientScale;\n"
570 "uniform myhalf DiffuseScale;\n"
571 "uniform myhalf SpecularScale;\n"
572 "uniform myhalf SpecularPower;\n"
574 "#ifdef USEOFFSETMAPPING\n"
575 "vec2 OffsetMapping(vec2 TexCoord)\n"
577 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
578 " // 14 sample relief mapping: linear search and then binary search\n"
579 " // this basically steps forward a small amount repeatedly until it finds\n"
580 " // itself inside solid, then jitters forward and back using decreasing\n"
581 " // amounts to find the impact\n"
582 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
583 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
584 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
585 " vec3 RT = vec3(TexCoord, 1);\n"
586 " OffsetVector *= 0.1;\n"
587 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
588 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
589 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
590 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
591 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
592 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
593 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
594 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
595 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
596 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
597 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
598 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
599 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
600 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
603 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
604 " // this basically moves forward the full distance, and then backs up based\n"
605 " // on height of samples\n"
606 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
607 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
608 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
609 " TexCoord += OffsetVector;\n"
610 " OffsetVector *= 0.333;\n"
611 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
612 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
613 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
614 " return TexCoord;\n"
621 "#ifdef USEOFFSETMAPPING\n"
622 " // apply offsetmapping\n"
623 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
624 "#define TexCoord TexCoordOffset\n"
627 " // combine the diffuse textures (base, pants, shirt)\n"
628 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
629 "#ifdef USECOLORMAPPING\n"
630 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
636 "#ifdef MODE_LIGHTSOURCE\n"
639 " // calculate surface normal, light normal, and specular normal\n"
640 " // compute color intensity for the two textures (colormap and glossmap)\n"
641 " // scale by light color and attenuation as efficiently as possible\n"
642 " // (do as much scalar math as possible rather than vector math)\n"
643 "#ifdef USESPECULAR\n"
644 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
645 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
646 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
648 " // calculate directional shading\n"
649 " 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"
651 "#ifdef USEDIFFUSE\n"
652 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
653 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
655 " // calculate directional shading\n"
656 " 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"
658 " // calculate directionless shading\n"
659 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
663 "#ifdef USECUBEFILTER\n"
664 " // apply light cubemap filter\n"
665 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
666 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
672 "#elif defined(MODE_LIGHTDIRECTION)\n"
673 " // directional model lighting\n"
675 " // get the surface normal and light normal\n"
676 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
677 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
679 " // calculate directional shading\n"
680 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
681 "#ifdef USESPECULAR\n"
682 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
683 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
689 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
690 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
692 " // get the surface normal and light normal\n"
693 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
695 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
696 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
697 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
699 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
701 " // calculate directional shading\n"
702 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
703 "#ifdef USESPECULAR\n"
704 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
705 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
708 " // apply lightmap color\n"
709 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
712 "#else // MODE none (lightmap)\n"
713 " // apply lightmap color\n"
714 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
717 " color *= myhvec4(gl_Color);\n"
720 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
725 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
729 "#ifdef MODE_LIGHTSOURCE\n"
730 " color.rgb *= color.a;\n"
732 " myhalf Fresnel = myhalf(max(pow(min(1, 1.0 - normalize(EyeVector).z), 5), 0.1));\n"
733 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
734 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
735 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect;\n"
736 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
737 " //color.rgb = myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)); // testing only\n"
738 " //color.rgb = myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)); // testing only\n"
739 " //vec4 RefractionPosition = ModelViewProjectionPosition + ModelViewProjectionPosition_svector * distort.x + ModelViewProjectionPosition_tvector * distort.y;\n"
740 " //vec4 ReflectionPosition = ModelViewProjectionPosition + ModelViewProjectionPosition_svector * distort.w + ModelViewProjectionPosition_tvector * distort.z;\n"
741 " //color.rgb += mix(myhvec3(texture2DProj(Texture_Refraction, RefractionPosition)) * RefractColor, myhvec3(texture2DProj(Texture_Reflection, ReflectionPosition)) * ReflectColor, Fresnel);\n"
745 "#ifdef USECONTRASTBOOST\n"
746 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
748 " color.rgb *= SceneBrightness;\n"
751 " gl_FragColor = vec4(color);\n"
754 "#endif // FRAGMENT_SHADER\n"
757 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
758 const char *permutationinfo[][2] =
760 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
761 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
762 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
763 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
764 {"#define USEWATER\n", " water"},
765 {"#define USEGLOW\n", " glow"},
766 {"#define USEFOG\n", " fog"},
767 {"#define USECOLORMAPPING\n", " colormapping"},
768 {"#define USEDIFFUSE\n", " diffuse"},
769 {"#define USECONTRASTBOOST\n", " contrastboost"},
770 {"#define USESPECULAR\n", " specular"},
771 {"#define USECUBEFILTER\n", " cubefilter"},
772 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
773 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
777 void R_GLSL_CompilePermutation(const char *filename, int permutation)
780 qboolean shaderfound;
781 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
782 int vertstrings_count;
783 int geomstrings_count;
784 int fragstrings_count;
786 const char *vertstrings_list[32+1];
787 const char *geomstrings_list[32+1];
788 const char *fragstrings_list[32+1];
789 char permutationname[256];
794 vertstrings_list[0] = "#define VERTEX_SHADER\n";
795 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
796 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
797 vertstrings_count = 1;
798 geomstrings_count = 1;
799 fragstrings_count = 1;
800 permutationname[0] = 0;
801 for (i = 0;permutationinfo[i][0];i++)
803 if (permutation & (1<<i))
805 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
806 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
807 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
808 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
812 // keep line numbers correct
813 vertstrings_list[vertstrings_count++] = "\n";
814 geomstrings_list[geomstrings_count++] = "\n";
815 fragstrings_list[fragstrings_count++] = "\n";
818 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
822 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
823 vertstrings_list[vertstrings_count++] = shaderstring;
824 geomstrings_list[geomstrings_count++] = shaderstring;
825 fragstrings_list[fragstrings_count++] = shaderstring;
828 else if (!strcmp(filename, "glsl/default.glsl"))
830 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
831 vertstrings_list[vertstrings_count++] = builtinshaderstring;
832 geomstrings_list[geomstrings_count++] = builtinshaderstring;
833 fragstrings_list[fragstrings_count++] = builtinshaderstring;
836 // clear any lists that are not needed by this shader
837 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
838 vertstrings_count = 0;
839 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
840 geomstrings_count = 0;
841 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
842 fragstrings_count = 0;
843 // compile the shader program
844 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
845 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
849 qglUseProgramObjectARB(p->program);CHECKGLERROR
850 // look up all the uniform variable names we care about, so we don't
851 // have to look them up every time we set them
852 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
853 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
854 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
855 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
856 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
857 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
858 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
859 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
860 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
861 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
862 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
863 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
864 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
865 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
866 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
867 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
868 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
869 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
870 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
871 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
872 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
873 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
874 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
875 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
876 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
877 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
878 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
879 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
880 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
881 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
882 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
883 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
884 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
885 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
886 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
887 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
888 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
889 // initialize the samplers to refer to the texture units we use
890 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
891 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
892 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
893 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
894 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
895 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
896 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
897 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
898 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
899 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
900 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
901 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
902 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
904 qglUseProgramObjectARB(0);CHECKGLERROR
907 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
909 Mem_Free(shaderstring);
912 void R_GLSL_Restart_f(void)
915 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
916 if (r_glsl_permutations[i].program)
917 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
918 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
921 void R_GLSL_DumpShader_f(void)
925 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
928 Con_Printf("failed to write to glsl/default.glsl\n");
932 FS_Print(file, "// The engine may define the following macros:\n");
933 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
934 for (i = 0;permutationinfo[i][0];i++)
935 FS_Printf(file, "// %s", permutationinfo[i][0]);
936 FS_Print(file, "\n");
937 FS_Print(file, builtinshaderstring);
940 Con_Printf("glsl/default.glsl written\n");
943 extern rtexture_t *r_shadow_attenuationgradienttexture;
944 extern rtexture_t *r_shadow_attenuation2dtexture;
945 extern rtexture_t *r_shadow_attenuation3dtexture;
946 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
948 // select a permutation of the lighting shader appropriate to this
949 // combination of texture, entity, light source, and fogging, only use the
950 // minimum features necessary to avoid wasting rendering time in the
951 // fragment shader on features that are not being used
952 const char *shaderfilename = NULL;
953 unsigned int permutation = 0;
955 r_glsl_permutation = NULL;
956 // TODO: implement geometry-shader based shadow volumes someday
957 if (rsurface.rtlight)
960 shaderfilename = "glsl/default.glsl";
961 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
962 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
963 permutation |= SHADERPERMUTATION_CUBEFILTER;
964 if (diffusescale > 0)
965 permutation |= SHADERPERMUTATION_DIFFUSE;
966 if (specularscale > 0)
967 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
968 if (r_refdef.fogenabled)
969 permutation |= SHADERPERMUTATION_FOG;
970 if (rsurface.texture->colormapping)
971 permutation |= SHADERPERMUTATION_COLORMAPPING;
972 if (r_glsl_offsetmapping.integer)
974 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
975 if (r_glsl_offsetmapping_reliefmapping.integer)
976 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
978 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
979 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
980 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
981 permutation |= SHADERPERMUTATION_USEWATER;
983 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
985 // bright unshaded geometry
986 shaderfilename = "glsl/default.glsl";
987 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
988 if (rsurface.texture->currentskinframe->glow)
989 permutation |= SHADERPERMUTATION_GLOW;
990 if (r_refdef.fogenabled)
991 permutation |= SHADERPERMUTATION_FOG;
992 if (rsurface.texture->colormapping)
993 permutation |= SHADERPERMUTATION_COLORMAPPING;
994 if (r_glsl_offsetmapping.integer)
996 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
997 if (r_glsl_offsetmapping_reliefmapping.integer)
998 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1000 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1001 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1003 permutation |= SHADERPERMUTATION_USEWATER;
1005 else if (modellighting)
1007 // directional model lighting
1008 shaderfilename = "glsl/default.glsl";
1009 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1010 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1011 if (rsurface.texture->currentskinframe->glow)
1012 permutation |= SHADERPERMUTATION_GLOW;
1013 if (specularscale > 0)
1014 permutation |= SHADERPERMUTATION_SPECULAR;
1015 if (r_refdef.fogenabled)
1016 permutation |= SHADERPERMUTATION_FOG;
1017 if (rsurface.texture->colormapping)
1018 permutation |= SHADERPERMUTATION_COLORMAPPING;
1019 if (r_glsl_offsetmapping.integer)
1021 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1022 if (r_glsl_offsetmapping_reliefmapping.integer)
1023 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1025 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1026 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1027 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1028 permutation |= SHADERPERMUTATION_USEWATER;
1033 shaderfilename = "glsl/default.glsl";
1034 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1035 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1037 // deluxemapping (light direction texture)
1038 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1039 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1041 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1042 if (specularscale > 0)
1043 permutation |= SHADERPERMUTATION_SPECULAR;
1045 else if (r_glsl_deluxemapping.integer >= 2)
1047 // fake deluxemapping (uniform light direction in tangentspace)
1048 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1049 if (specularscale > 0)
1050 permutation |= SHADERPERMUTATION_SPECULAR;
1054 // ordinary lightmapping
1057 if (rsurface.texture->currentskinframe->glow)
1058 permutation |= SHADERPERMUTATION_GLOW;
1059 if (r_refdef.fogenabled)
1060 permutation |= SHADERPERMUTATION_FOG;
1061 if (rsurface.texture->colormapping)
1062 permutation |= SHADERPERMUTATION_COLORMAPPING;
1063 if (r_glsl_offsetmapping.integer)
1065 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1066 if (r_glsl_offsetmapping_reliefmapping.integer)
1067 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1069 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1070 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1071 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1072 permutation |= SHADERPERMUTATION_USEWATER;
1074 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1076 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1077 R_GLSL_CompilePermutation(shaderfilename, permutation);
1078 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1080 // remove features until we find a valid permutation
1082 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1086 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");
1087 Cvar_SetValueQuick(&r_glsl, 0);
1088 return 0; // no bit left to clear
1090 // reduce i more quickly whenever it would not remove any bits
1091 if (!(permutation & i))
1094 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1095 R_GLSL_CompilePermutation(shaderfilename, permutation);
1096 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1101 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1103 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1104 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1105 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1107 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1108 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1109 if (permutation & SHADERPERMUTATION_DIFFUSE)
1111 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1112 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1113 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1114 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1118 // ambient only is simpler
1119 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1120 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1121 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1122 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1125 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1127 if (r_glsl_permutation->loc_AmbientColor >= 0)
1128 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1129 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1130 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1131 if (r_glsl_permutation->loc_SpecularColor >= 0)
1132 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1133 if (r_glsl_permutation->loc_LightDir >= 0)
1134 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1138 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1139 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1140 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1142 nmap = rsurface.texture->currentskinframe->nmap;
1143 if (gl_lightmaps.integer)
1144 nmap = r_texture_blanknormalmap;
1145 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1146 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1147 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1148 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1149 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1150 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1151 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1152 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1153 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1154 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1155 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1156 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1157 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1158 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1159 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1161 // The formula used is actually:
1162 // color.rgb *= SceneBrightness;
1163 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1164 // I simplify that to
1165 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1166 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1168 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1169 // and do [[calculations]] here in the engine
1170 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1171 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1174 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1175 if (r_glsl_permutation->loc_FogColor >= 0)
1177 // additive passes are only darkened by fog, not tinted
1178 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1179 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1181 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1183 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1184 if (r_glsl_permutation->loc_Color_Pants >= 0)
1186 if (rsurface.texture->currentskinframe->pants)
1187 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1189 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1191 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1193 if (rsurface.texture->currentskinframe->shirt)
1194 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1196 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1198 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1199 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1200 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1201 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value, r_glsl_water_refractdistort.value, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value);
1202 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]);
1203 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]);
1204 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_RefractColor, r_glsl_water_refractcolor_r.value, r_glsl_water_refractcolor_g.value, r_glsl_water_refractcolor_b.value);
1205 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_ReflectColor, r_glsl_water_reflectcolor_r.value, r_glsl_water_reflectcolor_g.value, r_glsl_water_reflectcolor_b.value);
1210 void R_SwitchSurfaceShader(int permutation)
1212 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1214 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1216 qglUseProgramObjectARB(r_glsl_permutation->program);
1221 #define SKINFRAME_HASH 1024
1225 int loadsequence; // incremented each level change
1226 memexpandablearray_t array;
1227 skinframe_t *hash[SKINFRAME_HASH];
1231 void R_SkinFrame_PrepareForPurge(void)
1233 r_skinframe.loadsequence++;
1234 // wrap it without hitting zero
1235 if (r_skinframe.loadsequence >= 200)
1236 r_skinframe.loadsequence = 1;
1239 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1243 // mark the skinframe as used for the purging code
1244 skinframe->loadsequence = r_skinframe.loadsequence;
1247 void R_SkinFrame_Purge(void)
1251 for (i = 0;i < SKINFRAME_HASH;i++)
1253 for (s = r_skinframe.hash[i];s;s = s->next)
1255 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1257 if (s->base == r_texture_notexture) s->base = NULL;
1258 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1259 if (s->merged == s->base) s->merged = NULL;
1260 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1261 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1262 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1263 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1264 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1265 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1266 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1267 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1268 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1269 s->loadsequence = 0;
1275 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1279 char basename[MAX_QPATH];
1281 Image_StripImageExtension(name, basename, sizeof(basename));
1283 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1284 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1285 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1291 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1292 memset(item, 0, sizeof(*item));
1293 strlcpy(item->basename, basename, sizeof(item->basename));
1294 item->textureflags = textureflags;
1295 item->comparewidth = comparewidth;
1296 item->compareheight = compareheight;
1297 item->comparecrc = comparecrc;
1298 item->next = r_skinframe.hash[hashindex];
1299 r_skinframe.hash[hashindex] = item;
1301 R_SkinFrame_MarkUsed(item);
1305 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1307 // FIXME: it should be possible to disable loading various layers using
1308 // cvars, to prevent wasted loading time and memory usage if the user does
1310 qboolean loadnormalmap = true;
1311 qboolean loadgloss = true;
1312 qboolean loadpantsandshirt = true;
1313 qboolean loadglow = true;
1315 unsigned char *pixels;
1316 unsigned char *bumppixels;
1317 unsigned char *basepixels = NULL;
1318 int basepixels_width;
1319 int basepixels_height;
1320 skinframe_t *skinframe;
1322 if (cls.state == ca_dedicated)
1325 // return an existing skinframe if already loaded
1326 // if loading of the first image fails, don't make a new skinframe as it
1327 // would cause all future lookups of this to be missing
1328 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1329 if (skinframe && skinframe->base)
1332 basepixels = loadimagepixels(name, complain, 0, 0);
1333 if (basepixels == NULL)
1336 // we've got some pixels to store, so really allocate this new texture now
1338 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1339 skinframe->stain = NULL;
1340 skinframe->merged = NULL;
1341 skinframe->base = r_texture_notexture;
1342 skinframe->pants = NULL;
1343 skinframe->shirt = NULL;
1344 skinframe->nmap = r_texture_blanknormalmap;
1345 skinframe->gloss = NULL;
1346 skinframe->glow = NULL;
1347 skinframe->fog = NULL;
1349 basepixels_width = image_width;
1350 basepixels_height = image_height;
1351 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);
1353 if (textureflags & TEXF_ALPHA)
1355 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1356 if (basepixels[j] < 255)
1358 if (j < basepixels_width * basepixels_height * 4)
1360 // has transparent pixels
1361 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1362 for (j = 0;j < image_width * image_height * 4;j += 4)
1367 pixels[j+3] = basepixels[j+3];
1369 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);
1374 // _norm is the name used by tenebrae and has been adopted as standard
1377 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1379 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);
1383 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1385 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1386 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1387 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);
1389 Mem_Free(bumppixels);
1391 else if (r_shadow_bumpscale_basetexture.value > 0)
1393 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1394 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1395 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);
1399 // _luma is supported for tenebrae compatibility
1400 // (I think it's a very stupid name, but oh well)
1401 // _glow is the preferred name
1402 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;}
1403 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;}
1404 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;}
1405 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;}
1408 Mem_Free(basepixels);
1413 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)
1418 for (i = 0;i < width*height;i++)
1419 if (((unsigned char *)&palette[in[i]])[3] > 0)
1421 if (i == width*height)
1424 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1427 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)
1430 unsigned char *temp1, *temp2;
1431 skinframe_t *skinframe;
1433 if (cls.state == ca_dedicated)
1436 // if already loaded just return it, otherwise make a new skinframe
1437 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1438 if (skinframe && skinframe->base)
1441 skinframe->stain = NULL;
1442 skinframe->merged = NULL;
1443 skinframe->base = r_texture_notexture;
1444 skinframe->pants = NULL;
1445 skinframe->shirt = NULL;
1446 skinframe->nmap = r_texture_blanknormalmap;
1447 skinframe->gloss = NULL;
1448 skinframe->glow = NULL;
1449 skinframe->fog = NULL;
1451 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1455 if (bitsperpixel == 32)
1457 if (r_shadow_bumpscale_basetexture.value > 0)
1459 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1460 temp2 = temp1 + width * height * 4;
1461 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1462 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1465 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1466 if (textureflags & TEXF_ALPHA)
1468 for (i = 3;i < width * height * 4;i += 4)
1469 if (skindata[i] < 255)
1471 if (i < width * height * 4)
1473 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1474 memcpy(fogpixels, skindata, width * height * 4);
1475 for (i = 0;i < width * height * 4;i += 4)
1476 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1477 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1478 Mem_Free(fogpixels);
1482 else if (bitsperpixel == 8)
1484 if (r_shadow_bumpscale_basetexture.value > 0)
1486 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1487 temp2 = temp1 + width * height * 4;
1488 if (bitsperpixel == 32)
1489 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1492 // use either a custom palette or the quake palette
1493 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1494 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1496 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1499 // use either a custom palette, or the quake palette
1500 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
1501 if (!palette && loadglowtexture)
1502 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1503 if (!palette && loadpantsandshirt)
1505 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1506 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1508 if (skinframe->pants || skinframe->shirt)
1509 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1510 if (textureflags & TEXF_ALPHA)
1512 // if not using a custom alphapalette, use the quake one
1514 alphapalette = palette_alpha;
1515 for (i = 0;i < width * height;i++)
1516 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1518 if (i < width * height)
1519 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1526 skinframe_t *R_SkinFrame_LoadMissing(void)
1528 skinframe_t *skinframe;
1530 if (cls.state == ca_dedicated)
1533 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1534 skinframe->stain = NULL;
1535 skinframe->merged = NULL;
1536 skinframe->base = r_texture_notexture;
1537 skinframe->pants = NULL;
1538 skinframe->shirt = NULL;
1539 skinframe->nmap = r_texture_blanknormalmap;
1540 skinframe->gloss = NULL;
1541 skinframe->glow = NULL;
1542 skinframe->fog = NULL;
1547 void gl_main_start(void)
1552 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1553 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1555 alpha = 1 - exp(r / ((double)x*(double)x));
1556 if (x == FOGMASKTABLEWIDTH - 1)
1558 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1561 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1562 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1564 // set up r_skinframe loading system for textures
1565 memset(&r_skinframe, 0, sizeof(r_skinframe));
1566 r_skinframe.loadsequence = 1;
1567 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1569 r_main_texturepool = R_AllocTexturePool();
1570 R_BuildBlankTextures();
1572 if (gl_texturecubemap)
1575 R_BuildNormalizationCube();
1577 R_BuildFogTexture();
1578 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1579 memset(&r_waterstate, 0, sizeof(r_waterstate));
1580 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1581 memset(&r_svbsp, 0, sizeof (r_svbsp));
1584 void gl_main_shutdown(void)
1586 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1587 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1589 // clear out the r_skinframe state
1590 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1591 memset(&r_skinframe, 0, sizeof(r_skinframe));
1594 Mem_Free(r_svbsp.nodes);
1595 memset(&r_svbsp, 0, sizeof (r_svbsp));
1596 R_FreeTexturePool(&r_main_texturepool);
1597 r_texture_blanknormalmap = NULL;
1598 r_texture_white = NULL;
1599 r_texture_grey128 = NULL;
1600 r_texture_black = NULL;
1601 r_texture_whitecube = NULL;
1602 r_texture_normalizationcube = NULL;
1603 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1604 memset(&r_waterstate, 0, sizeof(r_waterstate));
1608 extern void CL_ParseEntityLump(char *entitystring);
1609 void gl_main_newmap(void)
1611 // FIXME: move this code to client
1613 char *entities, entname[MAX_QPATH];
1616 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1617 l = (int)strlen(entname) - 4;
1618 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1620 memcpy(entname + l, ".ent", 5);
1621 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1623 CL_ParseEntityLump(entities);
1628 if (cl.worldmodel->brush.entities)
1629 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1633 void GL_Main_Init(void)
1635 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1637 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1638 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1639 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1640 if (gamemode == GAME_NEHAHRA)
1642 Cvar_RegisterVariable (&gl_fogenable);
1643 Cvar_RegisterVariable (&gl_fogdensity);
1644 Cvar_RegisterVariable (&gl_fogred);
1645 Cvar_RegisterVariable (&gl_foggreen);
1646 Cvar_RegisterVariable (&gl_fogblue);
1647 Cvar_RegisterVariable (&gl_fogstart);
1648 Cvar_RegisterVariable (&gl_fogend);
1650 Cvar_RegisterVariable(&r_depthfirst);
1651 Cvar_RegisterVariable(&r_nearclip);
1652 Cvar_RegisterVariable(&r_showbboxes);
1653 Cvar_RegisterVariable(&r_showsurfaces);
1654 Cvar_RegisterVariable(&r_showtris);
1655 Cvar_RegisterVariable(&r_shownormals);
1656 Cvar_RegisterVariable(&r_showlighting);
1657 Cvar_RegisterVariable(&r_showshadowvolumes);
1658 Cvar_RegisterVariable(&r_showcollisionbrushes);
1659 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1660 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1661 Cvar_RegisterVariable(&r_showdisabledepthtest);
1662 Cvar_RegisterVariable(&r_drawportals);
1663 Cvar_RegisterVariable(&r_drawentities);
1664 Cvar_RegisterVariable(&r_cullentities_trace);
1665 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1666 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1667 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1668 Cvar_RegisterVariable(&r_drawviewmodel);
1669 Cvar_RegisterVariable(&r_speeds);
1670 Cvar_RegisterVariable(&r_fullbrights);
1671 Cvar_RegisterVariable(&r_wateralpha);
1672 Cvar_RegisterVariable(&r_dynamic);
1673 Cvar_RegisterVariable(&r_fullbright);
1674 Cvar_RegisterVariable(&r_shadows);
1675 Cvar_RegisterVariable(&r_shadows_throwdistance);
1676 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1677 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1678 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1679 Cvar_RegisterVariable(&r_textureunits);
1680 Cvar_RegisterVariable(&r_glsl);
1681 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1682 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1683 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1684 Cvar_RegisterVariable(&r_glsl_water);
1685 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1686 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1687 Cvar_RegisterVariable(&r_glsl_water_refractcolor_r);
1688 Cvar_RegisterVariable(&r_glsl_water_refractcolor_g);
1689 Cvar_RegisterVariable(&r_glsl_water_refractcolor_b);
1690 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_r);
1691 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_g);
1692 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_b);
1693 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1694 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1695 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1696 Cvar_RegisterVariable(&r_lerpsprites);
1697 Cvar_RegisterVariable(&r_lerpmodels);
1698 Cvar_RegisterVariable(&r_waterscroll);
1699 Cvar_RegisterVariable(&r_bloom);
1700 Cvar_RegisterVariable(&r_bloom_colorscale);
1701 Cvar_RegisterVariable(&r_bloom_brighten);
1702 Cvar_RegisterVariable(&r_bloom_blur);
1703 Cvar_RegisterVariable(&r_bloom_resolution);
1704 Cvar_RegisterVariable(&r_bloom_colorexponent);
1705 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1706 Cvar_RegisterVariable(&r_hdr);
1707 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1708 Cvar_RegisterVariable(&r_glsl_contrastboost);
1709 Cvar_RegisterVariable(&r_hdr_glowintensity);
1710 Cvar_RegisterVariable(&r_hdr_range);
1711 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1712 Cvar_RegisterVariable(&developer_texturelogging);
1713 Cvar_RegisterVariable(&gl_lightmaps);
1714 Cvar_RegisterVariable(&r_test);
1715 Cvar_RegisterVariable(&r_batchmode);
1716 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1717 Cvar_SetValue("r_fullbrights", 0);
1718 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1721 extern void R_Textures_Init(void);
1722 extern void GL_Draw_Init(void);
1723 extern void GL_Main_Init(void);
1724 extern void R_Shadow_Init(void);
1725 extern void R_Sky_Init(void);
1726 extern void GL_Surf_Init(void);
1727 extern void R_Light_Init(void);
1728 extern void R_Particles_Init(void);
1729 extern void R_Explosion_Init(void);
1730 extern void gl_backend_init(void);
1731 extern void Sbar_Init(void);
1732 extern void R_LightningBeams_Init(void);
1733 extern void Mod_RenderInit(void);
1735 void Render_Init(void)
1748 R_LightningBeams_Init();
1757 extern char *ENGINE_EXTENSIONS;
1760 VID_CheckExtensions();
1762 // LordHavoc: report supported extensions
1763 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1765 // clear to black (loading plaque will be seen over this)
1767 qglClearColor(0,0,0,1);CHECKGLERROR
1768 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1771 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1775 for (i = 0;i < r_view.numfrustumplanes;i++)
1777 p = r_view.frustum + i;
1782 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1786 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1790 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1794 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1798 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1802 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1806 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1810 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1818 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1822 for (i = 0;i < numplanes;i++)
1829 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1833 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1837 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1841 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1845 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1849 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1853 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1857 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1865 //==================================================================================
1867 static void R_UpdateEntityLighting(entity_render_t *ent)
1869 vec3_t tempdiffusenormal;
1871 // fetch the lighting from the worldmodel data
1872 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));
1873 VectorClear(ent->modellight_diffuse);
1874 VectorClear(tempdiffusenormal);
1875 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1878 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1879 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1882 VectorSet(ent->modellight_ambient, 1, 1, 1);
1884 // move the light direction into modelspace coordinates for lighting code
1885 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1886 if(VectorLength2(ent->modellight_lightdir) > 0)
1888 VectorNormalize(ent->modellight_lightdir);
1892 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1895 // scale ambient and directional light contributions according to rendering variables
1896 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1897 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1898 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1899 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1900 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1901 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1904 static void R_View_UpdateEntityVisible (void)
1907 entity_render_t *ent;
1909 if (!r_drawentities.integer)
1912 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1913 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1915 // worldmodel can check visibility
1916 for (i = 0;i < r_refdef.numentities;i++)
1918 ent = r_refdef.entities[i];
1919 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));
1921 if(r_cullentities_trace.integer)
1923 for (i = 0;i < r_refdef.numentities;i++)
1925 ent = r_refdef.entities[i];
1926 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1928 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1929 ent->last_trace_visibility = realtime;
1930 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1931 r_viewcache.entityvisible[i] = 0;
1938 // no worldmodel or it can't check visibility
1939 for (i = 0;i < r_refdef.numentities;i++)
1941 ent = r_refdef.entities[i];
1942 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1946 // update entity lighting (even on hidden entities for r_shadows)
1947 for (i = 0;i < r_refdef.numentities;i++)
1948 R_UpdateEntityLighting(r_refdef.entities[i]);
1951 // only used if skyrendermasked, and normally returns false
1952 int R_DrawBrushModelsSky (void)
1955 entity_render_t *ent;
1957 if (!r_drawentities.integer)
1961 for (i = 0;i < r_refdef.numentities;i++)
1963 if (!r_viewcache.entityvisible[i])
1965 ent = r_refdef.entities[i];
1966 if (!ent->model || !ent->model->DrawSky)
1968 ent->model->DrawSky(ent);
1974 static void R_DrawNoModel(entity_render_t *ent);
1975 static void R_DrawModels(void)
1978 entity_render_t *ent;
1980 if (!r_drawentities.integer)
1983 for (i = 0;i < r_refdef.numentities;i++)
1985 if (!r_viewcache.entityvisible[i])
1987 ent = r_refdef.entities[i];
1988 r_refdef.stats.entities++;
1989 if (ent->model && ent->model->Draw != NULL)
1990 ent->model->Draw(ent);
1996 static void R_DrawModelsDepth(void)
1999 entity_render_t *ent;
2001 if (!r_drawentities.integer)
2004 for (i = 0;i < r_refdef.numentities;i++)
2006 if (!r_viewcache.entityvisible[i])
2008 ent = r_refdef.entities[i];
2009 r_refdef.stats.entities++;
2010 if (ent->model && ent->model->DrawDepth != NULL)
2011 ent->model->DrawDepth(ent);
2015 static void R_DrawModelsAddWaterPlanes(void)
2018 entity_render_t *ent;
2020 if (!r_drawentities.integer)
2023 for (i = 0;i < r_refdef.numentities;i++)
2025 if (!r_viewcache.entityvisible[i])
2027 ent = r_refdef.entities[i];
2028 r_refdef.stats.entities++;
2029 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2030 ent->model->DrawAddWaterPlanes(ent);
2034 static void R_View_SetFrustum(void)
2037 double slopex, slopey;
2039 // break apart the view matrix into vectors for various purposes
2040 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2041 VectorNegate(r_view.left, r_view.right);
2044 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2045 r_view.frustum[0].normal[1] = 0 - 0;
2046 r_view.frustum[0].normal[2] = -1 - 0;
2047 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2048 r_view.frustum[1].normal[1] = 0 + 0;
2049 r_view.frustum[1].normal[2] = -1 + 0;
2050 r_view.frustum[2].normal[0] = 0 - 0;
2051 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2052 r_view.frustum[2].normal[2] = -1 - 0;
2053 r_view.frustum[3].normal[0] = 0 + 0;
2054 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2055 r_view.frustum[3].normal[2] = -1 + 0;
2059 zNear = r_refdef.nearclip;
2060 nudge = 1.0 - 1.0 / (1<<23);
2061 r_view.frustum[4].normal[0] = 0 - 0;
2062 r_view.frustum[4].normal[1] = 0 - 0;
2063 r_view.frustum[4].normal[2] = -1 - -nudge;
2064 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2065 r_view.frustum[5].normal[0] = 0 + 0;
2066 r_view.frustum[5].normal[1] = 0 + 0;
2067 r_view.frustum[5].normal[2] = -1 + -nudge;
2068 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2074 r_view.frustum[0].normal[0] = m[3] - m[0];
2075 r_view.frustum[0].normal[1] = m[7] - m[4];
2076 r_view.frustum[0].normal[2] = m[11] - m[8];
2077 r_view.frustum[0].dist = m[15] - m[12];
2079 r_view.frustum[1].normal[0] = m[3] + m[0];
2080 r_view.frustum[1].normal[1] = m[7] + m[4];
2081 r_view.frustum[1].normal[2] = m[11] + m[8];
2082 r_view.frustum[1].dist = m[15] + m[12];
2084 r_view.frustum[2].normal[0] = m[3] - m[1];
2085 r_view.frustum[2].normal[1] = m[7] - m[5];
2086 r_view.frustum[2].normal[2] = m[11] - m[9];
2087 r_view.frustum[2].dist = m[15] - m[13];
2089 r_view.frustum[3].normal[0] = m[3] + m[1];
2090 r_view.frustum[3].normal[1] = m[7] + m[5];
2091 r_view.frustum[3].normal[2] = m[11] + m[9];
2092 r_view.frustum[3].dist = m[15] + m[13];
2094 r_view.frustum[4].normal[0] = m[3] - m[2];
2095 r_view.frustum[4].normal[1] = m[7] - m[6];
2096 r_view.frustum[4].normal[2] = m[11] - m[10];
2097 r_view.frustum[4].dist = m[15] - m[14];
2099 r_view.frustum[5].normal[0] = m[3] + m[2];
2100 r_view.frustum[5].normal[1] = m[7] + m[6];
2101 r_view.frustum[5].normal[2] = m[11] + m[10];
2102 r_view.frustum[5].dist = m[15] + m[14];
2107 if (r_view.useperspective)
2109 slopex = 1.0 / r_view.frustum_x;
2110 slopey = 1.0 / r_view.frustum_y;
2111 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2112 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2113 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2114 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2115 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2117 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2118 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2119 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2120 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2121 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2123 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2124 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2125 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2126 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2127 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2131 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2132 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2133 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2134 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2135 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2136 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2137 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2138 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2139 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2140 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2142 r_view.numfrustumplanes = 5;
2144 if (r_view.useclipplane)
2146 r_view.numfrustumplanes = 6;
2147 r_view.frustum[5] = r_view.clipplane;
2150 for (i = 0;i < r_view.numfrustumplanes;i++)
2151 PlaneClassify(r_view.frustum + i);
2153 // LordHavoc: note to all quake engine coders, Quake had a special case
2154 // for 90 degrees which assumed a square view (wrong), so I removed it,
2155 // Quake2 has it disabled as well.
2157 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2158 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2159 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2160 //PlaneClassify(&frustum[0]);
2162 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2163 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2164 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2165 //PlaneClassify(&frustum[1]);
2167 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2168 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2169 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2170 //PlaneClassify(&frustum[2]);
2172 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2173 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2174 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2175 //PlaneClassify(&frustum[3]);
2178 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2179 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2180 //PlaneClassify(&frustum[4]);
2183 void R_View_Update(void)
2185 R_View_SetFrustum();
2186 R_View_WorldVisibility(r_view.useclipplane);
2187 R_View_UpdateEntityVisible();
2190 void R_SetupView(void)
2192 if (!r_view.useperspective)
2193 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);
2194 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2195 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2197 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2199 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2201 if (r_view.useclipplane)
2203 // LordHavoc: couldn't figure out how to make this approach the
2204 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2205 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2206 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2207 dist = r_view.clipplane.dist;
2208 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2212 void R_ResetViewRendering2D(void)
2214 if (gl_support_fragment_shader)
2216 qglUseProgramObjectARB(0);CHECKGLERROR
2221 // GL is weird because it's bottom to top, r_view.y is top to bottom
2222 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2223 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2224 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2225 GL_Color(1, 1, 1, 1);
2226 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2227 GL_BlendFunc(GL_ONE, GL_ZERO);
2228 GL_AlphaTest(false);
2229 GL_ScissorTest(false);
2230 GL_DepthMask(false);
2231 GL_DepthRange(0, 1);
2232 GL_DepthTest(false);
2233 R_Mesh_Matrix(&identitymatrix);
2234 R_Mesh_ResetTextureState();
2235 GL_PolygonOffset(0, 0);
2236 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2237 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2238 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2239 qglStencilMask(~0);CHECKGLERROR
2240 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2241 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2242 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2245 void R_ResetViewRendering3D(void)
2247 if (gl_support_fragment_shader)
2249 qglUseProgramObjectARB(0);CHECKGLERROR
2254 // GL is weird because it's bottom to top, r_view.y is top to bottom
2255 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2257 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2258 GL_Color(1, 1, 1, 1);
2259 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2260 GL_BlendFunc(GL_ONE, GL_ZERO);
2261 GL_AlphaTest(false);
2262 GL_ScissorTest(true);
2264 GL_DepthRange(0, 1);
2266 R_Mesh_Matrix(&identitymatrix);
2267 R_Mesh_ResetTextureState();
2268 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2269 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2270 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2271 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2272 qglStencilMask(~0);CHECKGLERROR
2273 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2274 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2275 GL_CullFace(r_view.cullface_back);
2279 R_Bloom_SetupShader(
2281 "// written by Forest 'LordHavoc' Hale\n"
2283 "// common definitions between vertex shader and fragment shader:\n"
2285 "#ifdef __GLSL_CG_DATA_TYPES\n"
2286 "#define myhalf half\n"
2287 "#define myhvec2 hvec2\n"
2288 "#define myhvec3 hvec3\n"
2289 "#define myhvec4 hvec4\n"
2291 "#define myhalf float\n"
2292 "#define myhvec2 vec2\n"
2293 "#define myhvec3 vec3\n"
2294 "#define myhvec4 vec4\n"
2297 "varying vec2 ScreenTexCoord;\n"
2298 "varying vec2 BloomTexCoord;\n"
2303 "// vertex shader specific:\n"
2304 "#ifdef VERTEX_SHADER\n"
2308 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2309 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2310 " // transform vertex to camera space, using ftransform to match non-VS\n"
2312 " gl_Position = ftransform();\n"
2315 "#endif // VERTEX_SHADER\n"
2320 "// fragment shader specific:\n"
2321 "#ifdef FRAGMENT_SHADER\n"
2326 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2327 " for (x = -BLUR_X;x <= BLUR_X;x++)
2328 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2329 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2330 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2331 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2333 " gl_FragColor = vec4(color);\n"
2336 "#endif // FRAGMENT_SHADER\n"
2339 void R_RenderScene(qboolean addwaterplanes);
2341 static void R_Water_StartFrame(void)
2344 int texturewidth, textureheight;
2345 r_waterstate_waterplane_t *p;
2347 r_waterstate.maxwaterplanes = 0;
2349 // set waterwidth and waterheight to the water resolution that will be
2350 // used (often less than the screen resolution for faster rendering)
2351 r_waterstate.waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2352 r_waterstate.waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2354 // calculate desired texture sizes
2355 if (gl_support_arb_texture_non_power_of_two)
2357 texturewidth = r_waterstate.waterwidth;
2358 textureheight = r_waterstate.waterheight;
2362 for (texturewidth = 1;texturewidth < r_waterstate.waterwidth ;texturewidth *= 2);
2363 for (textureheight = 1;textureheight < r_waterstate.waterheight;textureheight *= 2);
2366 if (!r_glsl_water.integer)
2367 texturewidth = textureheight = 0;
2369 // allocate textures as needed
2370 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2372 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2374 if (p->texture_refraction)
2375 R_FreeTexture(p->texture_refraction);
2376 p->texture_refraction = NULL;
2377 if (p->texture_reflection)
2378 R_FreeTexture(p->texture_reflection);
2379 p->texture_reflection = NULL;
2381 r_waterstate.texturewidth = texturewidth;
2382 r_waterstate.textureheight = textureheight;
2385 if ((!texturewidth && !textureheight) || texturewidth > gl_max_texture_size || textureheight > gl_max_texture_size)
2387 // can't use water if the parameters are too weird
2388 // can't use water if the card does not support the texture size
2389 memset(&r_waterstate, 0, sizeof(r_waterstate));
2393 r_waterstate.enabled = true;
2395 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2397 // set up variables that will be used in shader setup
2398 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2399 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2400 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2401 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2404 static void R_Water_AddWaterPlane(msurface_t *surface)
2406 int triangleindex, planeindex;
2410 r_waterstate_waterplane_t *p;
2411 // just use the first triangle with a valid normal for any decisions
2412 VectorClear(normal);
2413 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2415 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2416 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2417 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2418 TriangleNormal(vert[0], vert[1], vert[2], normal);
2419 if (VectorLength2(normal) >= 0.001)
2422 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2423 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2425 // if this triangle does not fit any known plane rendered this frame, render textures for it
2426 if (planeindex >= r_waterstate.numwaterplanes && planeindex < r_waterstate.maxwaterplanes)
2428 // store the new plane
2429 r_waterstate.numwaterplanes++;
2430 VectorCopy(normal, p->plane.normal);
2431 VectorNormalize(p->plane.normal);
2432 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2433 PlaneClassify(&p->plane);
2434 // flip the plane if it does not face the viewer
2435 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2437 VectorNegate(p->plane.normal, p->plane.normal);
2438 p->plane.dist *= -1;
2439 PlaneClassify(&p->plane);
2444 static void R_Water_ProcessPlanes(void)
2446 r_view_t originalview;
2448 r_waterstate_waterplane_t *p;
2450 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2452 if (!p->texture_refraction)
2454 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);
2455 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);
2458 originalview = r_view;
2459 r_view.showdebug = false;
2460 r_view.width = r_waterstate.waterwidth;
2461 r_view.height = r_waterstate.waterheight;
2462 r_view.useclipplane = true;
2464 r_view.clipplane = p->plane;
2465 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2466 r_view.clipplane.dist = -r_view.clipplane.dist;
2467 PlaneClassify(&r_view.clipplane);
2468 r_waterstate.renderingscene = true;
2469 // render the normal view scene and copy into texture
2470 // (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)
2471 R_RenderScene(false);
2473 // copy view into the screen texture
2474 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2475 GL_ActiveTexture(0);
2477 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
2479 // render reflected scene and copy into texture
2480 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2481 r_view.clipplane = p->plane;
2482 // reverse the cullface settings for this render
2483 r_view.cullface_front = GL_FRONT;
2484 r_view.cullface_back = GL_BACK;
2486 R_ResetViewRendering3D();
2489 R_RenderScene(false);
2491 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2492 GL_ActiveTexture(0);
2494 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
2496 R_ResetViewRendering3D();
2499 r_view = originalview;
2500 r_waterstate.renderingscene = false;
2504 void R_Bloom_StartFrame(void)
2506 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2508 // set bloomwidth and bloomheight to the bloom resolution that will be
2509 // used (often less than the screen resolution for faster rendering)
2510 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2511 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2512 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2514 // calculate desired texture sizes
2515 if (gl_support_arb_texture_non_power_of_two)
2517 screentexturewidth = r_view.width;
2518 screentextureheight = r_view.height;
2519 bloomtexturewidth = r_bloomstate.bloomwidth;
2520 bloomtextureheight = r_bloomstate.bloomheight;
2524 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2525 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2526 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2527 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2532 screentexturewidth = screentextureheight = 0;
2534 else if (r_bloom.integer)
2539 screentexturewidth = screentextureheight = 0;
2540 bloomtexturewidth = bloomtextureheight = 0;
2543 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)
2545 // can't use bloom if the parameters are too weird
2546 // can't use bloom if the card does not support the texture size
2547 if (r_bloomstate.texture_screen)
2548 R_FreeTexture(r_bloomstate.texture_screen);
2549 if (r_bloomstate.texture_bloom)
2550 R_FreeTexture(r_bloomstate.texture_bloom);
2551 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2555 r_bloomstate.enabled = true;
2556 r_bloomstate.hdr = r_hdr.integer != 0;
2558 // allocate textures as needed
2559 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2561 if (r_bloomstate.texture_screen)
2562 R_FreeTexture(r_bloomstate.texture_screen);
2563 r_bloomstate.texture_screen = NULL;
2564 r_bloomstate.screentexturewidth = screentexturewidth;
2565 r_bloomstate.screentextureheight = screentextureheight;
2566 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2567 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);
2569 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2571 if (r_bloomstate.texture_bloom)
2572 R_FreeTexture(r_bloomstate.texture_bloom);
2573 r_bloomstate.texture_bloom = NULL;
2574 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2575 r_bloomstate.bloomtextureheight = bloomtextureheight;
2576 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2577 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);
2580 // set up a texcoord array for the full resolution screen image
2581 // (we have to keep this around to copy back during final render)
2582 r_bloomstate.screentexcoord2f[0] = 0;
2583 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2584 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2585 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2586 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2587 r_bloomstate.screentexcoord2f[5] = 0;
2588 r_bloomstate.screentexcoord2f[6] = 0;
2589 r_bloomstate.screentexcoord2f[7] = 0;
2591 // set up a texcoord array for the reduced resolution bloom image
2592 // (which will be additive blended over the screen image)
2593 r_bloomstate.bloomtexcoord2f[0] = 0;
2594 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2595 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2596 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2597 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2598 r_bloomstate.bloomtexcoord2f[5] = 0;
2599 r_bloomstate.bloomtexcoord2f[6] = 0;
2600 r_bloomstate.bloomtexcoord2f[7] = 0;
2603 void R_Bloom_CopyScreenTexture(float colorscale)
2605 r_refdef.stats.bloom++;
2607 R_ResetViewRendering2D();
2608 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2609 R_Mesh_ColorPointer(NULL, 0, 0);
2610 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2611 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2613 // copy view into the screen texture
2614 GL_ActiveTexture(0);
2616 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
2617 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2619 // now scale it down to the bloom texture size
2621 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2622 GL_BlendFunc(GL_ONE, GL_ZERO);
2623 GL_Color(colorscale, colorscale, colorscale, 1);
2624 // TODO: optimize with multitexture or GLSL
2625 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2626 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2628 // we now have a bloom image in the framebuffer
2629 // copy it into the bloom image texture for later processing
2630 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2631 GL_ActiveTexture(0);
2633 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
2634 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2637 void R_Bloom_CopyHDRTexture(void)
2639 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2640 GL_ActiveTexture(0);
2642 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
2643 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2646 void R_Bloom_MakeTexture(void)
2649 float xoffset, yoffset, r, brighten;
2651 r_refdef.stats.bloom++;
2653 R_ResetViewRendering2D();
2654 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2655 R_Mesh_ColorPointer(NULL, 0, 0);
2657 // we have a bloom image in the framebuffer
2659 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2661 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2664 r = bound(0, r_bloom_colorexponent.value / x, 1);
2665 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2666 GL_Color(r, r, r, 1);
2667 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2668 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2669 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2670 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2672 // copy the vertically blurred bloom view to a texture
2673 GL_ActiveTexture(0);
2675 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
2676 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2679 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2680 brighten = r_bloom_brighten.value;
2682 brighten *= r_hdr_range.value;
2683 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2684 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2686 for (dir = 0;dir < 2;dir++)
2688 // blend on at multiple vertical offsets to achieve a vertical blur
2689 // TODO: do offset blends using GLSL
2690 GL_BlendFunc(GL_ONE, GL_ZERO);
2691 for (x = -range;x <= range;x++)
2693 if (!dir){xoffset = 0;yoffset = x;}
2694 else {xoffset = x;yoffset = 0;}
2695 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2696 yoffset /= (float)r_bloomstate.bloomtextureheight;
2697 // compute a texcoord array with the specified x and y offset
2698 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2699 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2700 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2701 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2702 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2703 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2704 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2705 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2706 // this r value looks like a 'dot' particle, fading sharply to
2707 // black at the edges
2708 // (probably not realistic but looks good enough)
2709 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2710 //r = (dir ? 1.0f : brighten)/(range*2+1);
2711 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2712 GL_Color(r, r, r, 1);
2713 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2714 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2715 GL_BlendFunc(GL_ONE, GL_ONE);
2718 // copy the vertically blurred bloom view to a texture
2719 GL_ActiveTexture(0);
2721 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
2722 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2725 // apply subtract last
2726 // (just like it would be in a GLSL shader)
2727 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2729 GL_BlendFunc(GL_ONE, GL_ZERO);
2730 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2731 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2732 GL_Color(1, 1, 1, 1);
2733 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2734 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2736 GL_BlendFunc(GL_ONE, GL_ONE);
2737 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2738 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2739 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2740 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2741 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2742 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2743 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2745 // copy the darkened bloom view to a texture
2746 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2747 GL_ActiveTexture(0);
2749 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
2750 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2754 void R_HDR_RenderBloomTexture(void)
2756 int oldwidth, oldheight;
2758 oldwidth = r_view.width;
2759 oldheight = r_view.height;
2760 r_view.width = r_bloomstate.bloomwidth;
2761 r_view.height = r_bloomstate.bloomheight;
2763 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2764 // TODO: add exposure compensation features
2765 // TODO: add fp16 framebuffer support
2767 r_view.showdebug = false;
2768 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2770 r_view.colorscale /= r_hdr_range.value;
2771 r_waterstate.numwaterplanes = 0;
2772 R_RenderScene(r_waterstate.enabled);
2773 r_view.showdebug = true;
2775 R_ResetViewRendering2D();
2777 R_Bloom_CopyHDRTexture();
2778 R_Bloom_MakeTexture();
2780 R_ResetViewRendering3D();
2783 if (r_timereport_active)
2784 R_TimeReport("clear");
2787 // restore the view settings
2788 r_view.width = oldwidth;
2789 r_view.height = oldheight;
2792 static void R_BlendView(void)
2794 if (r_bloomstate.enabled && r_bloomstate.hdr)
2796 // render high dynamic range bloom effect
2797 // the bloom texture was made earlier this render, so we just need to
2798 // blend it onto the screen...
2799 R_ResetViewRendering2D();
2800 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2801 R_Mesh_ColorPointer(NULL, 0, 0);
2802 GL_Color(1, 1, 1, 1);
2803 GL_BlendFunc(GL_ONE, GL_ONE);
2804 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2805 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2806 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2807 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2809 else if (r_bloomstate.enabled)
2811 // render simple bloom effect
2812 // copy the screen and shrink it and darken it for the bloom process
2813 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2814 // make the bloom texture
2815 R_Bloom_MakeTexture();
2816 // put the original screen image back in place and blend the bloom
2818 R_ResetViewRendering2D();
2819 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2820 R_Mesh_ColorPointer(NULL, 0, 0);
2821 GL_Color(1, 1, 1, 1);
2822 GL_BlendFunc(GL_ONE, GL_ZERO);
2823 // do both in one pass if possible
2824 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2825 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2826 if (r_textureunits.integer >= 2 && gl_combine.integer)
2828 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2829 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2830 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2834 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2835 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2836 // now blend on the bloom texture
2837 GL_BlendFunc(GL_ONE, GL_ONE);
2838 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2839 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2841 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2842 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2844 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2846 // apply a color tint to the whole view
2847 R_ResetViewRendering2D();
2848 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2849 R_Mesh_ColorPointer(NULL, 0, 0);
2850 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2851 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2852 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2856 void R_RenderScene(qboolean addwaterplanes);
2858 matrix4x4_t r_waterscrollmatrix;
2860 void R_UpdateVariables(void)
2864 r_refdef.farclip = 4096;
2865 if (r_refdef.worldmodel)
2866 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2867 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2869 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2870 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2871 r_refdef.polygonfactor = 0;
2872 r_refdef.polygonoffset = 0;
2873 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2874 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2876 r_refdef.rtworld = r_shadow_realtime_world.integer;
2877 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2878 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2879 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2880 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2881 if (r_showsurfaces.integer)
2883 r_refdef.rtworld = false;
2884 r_refdef.rtworldshadows = false;
2885 r_refdef.rtdlight = false;
2886 r_refdef.rtdlightshadows = false;
2887 r_refdef.lightmapintensity = 0;
2890 if (gamemode == GAME_NEHAHRA)
2892 if (gl_fogenable.integer)
2894 r_refdef.oldgl_fogenable = true;
2895 r_refdef.fog_density = gl_fogdensity.value;
2896 r_refdef.fog_red = gl_fogred.value;
2897 r_refdef.fog_green = gl_foggreen.value;
2898 r_refdef.fog_blue = gl_fogblue.value;
2900 else if (r_refdef.oldgl_fogenable)
2902 r_refdef.oldgl_fogenable = false;
2903 r_refdef.fog_density = 0;
2904 r_refdef.fog_red = 0;
2905 r_refdef.fog_green = 0;
2906 r_refdef.fog_blue = 0;
2909 if (r_refdef.fog_density)
2911 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2912 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2913 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2915 if (r_refdef.fog_density)
2917 r_refdef.fogenabled = true;
2918 // this is the point where the fog reaches 0.9986 alpha, which we
2919 // consider a good enough cutoff point for the texture
2920 // (0.9986 * 256 == 255.6)
2921 r_refdef.fogrange = 400 / r_refdef.fog_density;
2922 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2923 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2924 // fog color was already set
2927 r_refdef.fogenabled = false;
2935 void R_RenderView(void)
2937 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2938 return; //Host_Error ("R_RenderView: NULL worldmodel");
2940 R_Shadow_UpdateWorldLightSelection();
2942 R_Bloom_StartFrame();
2943 R_Water_StartFrame();
2946 if (r_timereport_active)
2947 R_TimeReport("setup");
2949 R_ResetViewRendering3D();
2952 if (r_timereport_active)
2953 R_TimeReport("clear");
2955 r_view.showdebug = true;
2957 // this produces a bloom texture to be used in R_BlendView() later
2959 R_HDR_RenderBloomTexture();
2961 r_view.colorscale = r_hdr_scenebrightness.value;
2962 r_waterstate.numwaterplanes = 0;
2963 R_RenderScene(r_waterstate.enabled);
2966 if (r_timereport_active)
2967 R_TimeReport("blendview");
2969 GL_Scissor(0, 0, vid.width, vid.height);
2970 GL_ScissorTest(false);
2974 extern void R_DrawLightningBeams (void);
2975 extern void VM_CL_AddPolygonsToMeshQueue (void);
2976 extern void R_DrawPortals (void);
2977 extern cvar_t cl_locs_show;
2978 static void R_DrawLocs(void);
2979 static void R_DrawEntityBBoxes(void);
2980 void R_RenderScene(qboolean addwaterplanes)
2984 R_ResetViewRendering3D();
2987 if (r_timereport_active)
2988 R_TimeReport("watervisibility");
2990 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2992 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
2993 if (r_timereport_active)
2994 R_TimeReport("waterworld");
2997 // don't let sound skip if going slow
2998 if (r_refdef.extraupdate)
3001 R_DrawModelsAddWaterPlanes();
3002 if (r_timereport_active)
3003 R_TimeReport("watermodels");
3005 R_Water_ProcessPlanes();
3006 if (r_timereport_active)
3007 R_TimeReport("waterscenes");
3010 R_ResetViewRendering3D();
3012 // don't let sound skip if going slow
3013 if (r_refdef.extraupdate)
3016 R_MeshQueue_BeginScene();
3021 if (r_timereport_active)
3022 R_TimeReport("visibility");
3024 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);
3026 if (cl.csqc_vidvars.drawworld)
3028 // don't let sound skip if going slow
3029 if (r_refdef.extraupdate)
3032 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3034 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3035 if (r_timereport_active)
3036 R_TimeReport("worldsky");
3039 if (R_DrawBrushModelsSky() && r_timereport_active)
3040 R_TimeReport("bmodelsky");
3043 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3045 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3046 if (r_timereport_active)
3047 R_TimeReport("worlddepth");
3049 if (r_depthfirst.integer >= 2)
3051 R_DrawModelsDepth();
3052 if (r_timereport_active)
3053 R_TimeReport("modeldepth");
3056 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3058 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3059 if (r_timereport_active)
3060 R_TimeReport("world");
3063 // don't let sound skip if going slow
3064 if (r_refdef.extraupdate)
3068 if (r_timereport_active)
3069 R_TimeReport("models");
3071 // don't let sound skip if going slow
3072 if (r_refdef.extraupdate)
3075 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3077 R_DrawModelShadows();
3079 R_ResetViewRendering3D();
3081 // don't let sound skip if going slow
3082 if (r_refdef.extraupdate)
3086 R_ShadowVolumeLighting(false);
3087 if (r_timereport_active)
3088 R_TimeReport("rtlights");
3090 // don't let sound skip if going slow
3091 if (r_refdef.extraupdate)
3094 if (cl.csqc_vidvars.drawworld)
3096 R_DrawLightningBeams();
3097 if (r_timereport_active)
3098 R_TimeReport("lightning");
3101 if (r_timereport_active)
3102 R_TimeReport("particles");
3105 if (r_timereport_active)
3106 R_TimeReport("explosions");
3109 if (gl_support_fragment_shader)
3111 qglUseProgramObjectARB(0);CHECKGLERROR
3113 VM_CL_AddPolygonsToMeshQueue();
3115 if (r_view.showdebug)
3117 if (cl_locs_show.integer)
3120 if (r_timereport_active)
3121 R_TimeReport("showlocs");
3124 if (r_drawportals.integer)
3127 if (r_timereport_active)
3128 R_TimeReport("portals");
3131 if (r_showbboxes.value > 0)
3133 R_DrawEntityBBoxes();
3134 if (r_timereport_active)
3135 R_TimeReport("bboxes");
3139 if (gl_support_fragment_shader)
3141 qglUseProgramObjectARB(0);CHECKGLERROR
3143 R_MeshQueue_RenderTransparent();
3144 if (r_timereport_active)
3145 R_TimeReport("drawtrans");
3147 if (gl_support_fragment_shader)
3149 qglUseProgramObjectARB(0);CHECKGLERROR
3152 if (cl.csqc_vidvars.drawworld)
3155 if (r_timereport_active)
3156 R_TimeReport("coronas");
3159 // don't let sound skip if going slow
3160 if (r_refdef.extraupdate)
3163 R_ResetViewRendering2D();
3166 static const int bboxelements[36] =
3176 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3179 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3180 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3181 GL_DepthMask(false);
3182 GL_DepthRange(0, 1);
3183 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3184 R_Mesh_Matrix(&identitymatrix);
3185 R_Mesh_ResetTextureState();
3187 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3188 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3189 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3190 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3191 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3192 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3193 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3194 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3195 R_FillColors(color4f, 8, cr, cg, cb, ca);
3196 if (r_refdef.fogenabled)
3198 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3200 f1 = FogPoint_World(v);
3202 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3203 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3204 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3207 R_Mesh_VertexPointer(vertex3f, 0, 0);
3208 R_Mesh_ColorPointer(color4f, 0, 0);
3209 R_Mesh_ResetTextureState();
3210 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3213 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3217 prvm_edict_t *edict;
3218 // this function draws bounding boxes of server entities
3222 for (i = 0;i < numsurfaces;i++)
3224 edict = PRVM_EDICT_NUM(surfacelist[i]);
3225 switch ((int)edict->fields.server->solid)
3227 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3228 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3229 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3230 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3231 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3232 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3234 color[3] *= r_showbboxes.value;
3235 color[3] = bound(0, color[3], 1);
3236 GL_DepthTest(!r_showdisabledepthtest.integer);
3237 GL_CullFace(r_view.cullface_front);
3238 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3243 static void R_DrawEntityBBoxes(void)
3246 prvm_edict_t *edict;
3248 // this function draws bounding boxes of server entities
3252 for (i = 0;i < prog->num_edicts;i++)
3254 edict = PRVM_EDICT_NUM(i);
3255 if (edict->priv.server->free)
3257 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3258 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3263 int nomodelelements[24] =
3275 float nomodelvertex3f[6*3] =
3285 float nomodelcolor4f[6*4] =
3287 0.0f, 0.0f, 0.5f, 1.0f,
3288 0.0f, 0.0f, 0.5f, 1.0f,
3289 0.0f, 0.5f, 0.0f, 1.0f,
3290 0.0f, 0.5f, 0.0f, 1.0f,
3291 0.5f, 0.0f, 0.0f, 1.0f,
3292 0.5f, 0.0f, 0.0f, 1.0f
3295 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3300 // this is only called once per entity so numsurfaces is always 1, and
3301 // surfacelist is always {0}, so this code does not handle batches
3302 R_Mesh_Matrix(&ent->matrix);
3304 if (ent->flags & EF_ADDITIVE)
3306 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3307 GL_DepthMask(false);
3309 else if (ent->alpha < 1)
3311 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3312 GL_DepthMask(false);
3316 GL_BlendFunc(GL_ONE, GL_ZERO);
3319 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3320 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3321 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3322 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3323 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3324 if (r_refdef.fogenabled)
3327 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3328 R_Mesh_ColorPointer(color4f, 0, 0);
3329 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3330 f1 = FogPoint_World(org);
3332 for (i = 0, c = color4f;i < 6;i++, c += 4)
3334 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3335 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3336 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3340 else if (ent->alpha != 1)
3342 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3343 R_Mesh_ColorPointer(color4f, 0, 0);
3344 for (i = 0, c = color4f;i < 6;i++, c += 4)
3348 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3349 R_Mesh_ResetTextureState();
3350 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3353 void R_DrawNoModel(entity_render_t *ent)
3356 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3357 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3358 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3360 // R_DrawNoModelCallback(ent, 0);
3363 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3365 vec3_t right1, right2, diff, normal;
3367 VectorSubtract (org2, org1, normal);
3369 // calculate 'right' vector for start
3370 VectorSubtract (r_view.origin, org1, diff);
3371 CrossProduct (normal, diff, right1);
3372 VectorNormalize (right1);
3374 // calculate 'right' vector for end
3375 VectorSubtract (r_view.origin, org2, diff);
3376 CrossProduct (normal, diff, right2);
3377 VectorNormalize (right2);
3379 vert[ 0] = org1[0] + width * right1[0];
3380 vert[ 1] = org1[1] + width * right1[1];
3381 vert[ 2] = org1[2] + width * right1[2];
3382 vert[ 3] = org1[0] - width * right1[0];
3383 vert[ 4] = org1[1] - width * right1[1];
3384 vert[ 5] = org1[2] - width * right1[2];
3385 vert[ 6] = org2[0] - width * right2[0];
3386 vert[ 7] = org2[1] - width * right2[1];
3387 vert[ 8] = org2[2] - width * right2[2];
3388 vert[ 9] = org2[0] + width * right2[0];
3389 vert[10] = org2[1] + width * right2[1];
3390 vert[11] = org2[2] + width * right2[2];
3393 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3395 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)
3400 if (r_refdef.fogenabled)
3401 fog = FogPoint_World(origin);
3403 R_Mesh_Matrix(&identitymatrix);
3404 GL_BlendFunc(blendfunc1, blendfunc2);
3410 GL_CullFace(r_view.cullface_front);
3413 GL_CullFace(r_view.cullface_back);
3415 GL_DepthMask(false);
3416 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3417 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3418 GL_DepthTest(!depthdisable);
3420 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3421 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3422 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3423 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3424 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3425 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3426 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3427 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3428 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3429 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3430 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3431 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3433 R_Mesh_VertexPointer(vertex3f, 0, 0);
3434 R_Mesh_ColorPointer(NULL, 0, 0);
3435 R_Mesh_ResetTextureState();
3436 R_Mesh_TexBind(0, R_GetTexture(texture));
3437 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3438 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3439 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3440 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3442 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3444 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3445 GL_BlendFunc(blendfunc1, GL_ONE);
3447 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);
3448 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3452 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3457 VectorSet(v, x, y, z);
3458 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3459 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3461 if (i == mesh->numvertices)
3463 if (mesh->numvertices < mesh->maxvertices)
3465 VectorCopy(v, vertex3f);
3466 mesh->numvertices++;
3468 return mesh->numvertices;
3474 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3478 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3479 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3480 e = mesh->element3i + mesh->numtriangles * 3;
3481 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3483 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3484 if (mesh->numtriangles < mesh->maxtriangles)
3489 mesh->numtriangles++;
3491 element[1] = element[2];
3495 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3499 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3500 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3501 e = mesh->element3i + mesh->numtriangles * 3;
3502 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3504 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3505 if (mesh->numtriangles < mesh->maxtriangles)
3510 mesh->numtriangles++;
3512 element[1] = element[2];
3516 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3517 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3519 int planenum, planenum2;
3522 mplane_t *plane, *plane2;
3524 double temppoints[2][256*3];
3525 // figure out how large a bounding box we need to properly compute this brush
3527 for (w = 0;w < numplanes;w++)
3528 maxdist = max(maxdist, planes[w].dist);
3529 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3530 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3531 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3535 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3536 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3538 if (planenum2 == planenum)
3540 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);
3543 if (tempnumpoints < 3)
3545 // generate elements forming a triangle fan for this polygon
3546 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3550 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3553 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3554 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3555 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3556 GL_LockArrays(0, brush->numpoints);
3557 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3558 GL_LockArrays(0, 0);
3561 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3564 if (!surface->num_collisiontriangles)
3566 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3567 i = (int)(((size_t)surface) / sizeof(msurface_t));
3568 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3569 GL_LockArrays(0, surface->num_collisionvertices);
3570 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3571 GL_LockArrays(0, 0);
3574 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)
3576 texturelayer_t *layer;
3577 layer = t->currentlayers + t->currentnumlayers++;
3579 layer->depthmask = depthmask;
3580 layer->blendfunc1 = blendfunc1;
3581 layer->blendfunc2 = blendfunc2;
3582 layer->texture = texture;
3583 layer->texmatrix = *matrix;
3584 layer->color[0] = r * r_view.colorscale;
3585 layer->color[1] = g * r_view.colorscale;
3586 layer->color[2] = b * r_view.colorscale;
3587 layer->color[3] = a;
3590 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3593 index = parms[2] + r_refdef.time * parms[3];
3594 index -= floor(index);
3598 case Q3WAVEFUNC_NONE:
3599 case Q3WAVEFUNC_NOISE:
3600 case Q3WAVEFUNC_COUNT:
3603 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3604 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3605 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3606 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3607 case Q3WAVEFUNC_TRIANGLE:
3609 f = index - floor(index);
3620 return (float)(parms[0] + parms[1] * f);
3623 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3626 model_t *model = ent->model;
3629 q3shaderinfo_layer_tcmod_t *tcmod;
3631 // switch to an alternate material if this is a q1bsp animated material
3633 texture_t *texture = t;
3634 int s = ent->skinnum;
3635 if ((unsigned int)s >= (unsigned int)model->numskins)
3637 if (model->skinscenes)
3639 if (model->skinscenes[s].framecount > 1)
3640 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3642 s = model->skinscenes[s].firstframe;
3645 t = t + s * model->num_surfaces;
3648 // use an alternate animation if the entity's frame is not 0,
3649 // and only if the texture has an alternate animation
3650 if (ent->frame2 != 0 && t->anim_total[1])
3651 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3653 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3655 texture->currentframe = t;
3658 // update currentskinframe to be a qw skin or animation frame
3659 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3661 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3663 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3664 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3665 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);
3667 t->currentskinframe = r_qwskincache_skinframe[i];
3668 if (t->currentskinframe == NULL)
3669 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3671 else if (t->numskinframes >= 2)
3672 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3673 if (t->backgroundnumskinframes >= 2)
3674 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3676 t->currentmaterialflags = t->basematerialflags;
3677 t->currentalpha = ent->alpha;
3678 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3680 t->currentalpha *= r_wateralpha.value;
3681 // if rendering refraction/reflection, disable transparency
3682 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3683 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3685 if (!(ent->flags & RENDER_LIGHT))
3686 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3687 if (ent->effects & EF_ADDITIVE)
3688 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3689 else if (t->currentalpha < 1)
3690 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3691 if (ent->effects & EF_DOUBLESIDED)
3692 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3693 if (ent->effects & EF_NODEPTHTEST)
3694 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3695 if (ent->flags & RENDER_VIEWMODEL)
3696 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3697 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3698 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3699 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3700 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3702 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3705 switch(tcmod->tcmod)
3709 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3710 matrix = r_waterscrollmatrix;
3712 matrix = identitymatrix;
3714 case Q3TCMOD_ENTITYTRANSLATE:
3715 // this is used in Q3 to allow the gamecode to control texcoord
3716 // scrolling on the entity, which is not supported in darkplaces yet.
3717 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3719 case Q3TCMOD_ROTATE:
3720 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3721 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3722 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3725 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3727 case Q3TCMOD_SCROLL:
3728 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3730 case Q3TCMOD_STRETCH:
3731 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3732 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3734 case Q3TCMOD_TRANSFORM:
3735 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3736 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3737 VectorSet(tcmat + 6, 0 , 0 , 1);
3738 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3739 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3741 case Q3TCMOD_TURBULENT:
3742 // this is handled in the RSurf_PrepareVertices function
3743 matrix = identitymatrix;
3746 // either replace or concatenate the transformation
3748 t->currenttexmatrix = matrix;
3751 matrix4x4_t temp = t->currenttexmatrix;
3752 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3756 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3757 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3758 t->glosstexture = r_texture_white;
3759 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3760 t->backgroundglosstexture = r_texture_white;
3761 t->specularpower = r_shadow_glossexponent.value;
3762 // TODO: store reference values for these in the texture?
3763 t->specularscale = 0;
3764 if (r_shadow_gloss.integer > 0)
3766 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3768 if (r_shadow_glossintensity.value > 0)
3770 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3771 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3772 t->specularscale = r_shadow_glossintensity.value;
3775 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3776 t->specularscale = r_shadow_gloss2intensity.value;
3779 // lightmaps mode looks bad with dlights using actual texturing, so turn
3780 // off the colormap and glossmap, but leave the normalmap on as it still
3781 // accurately represents the shading involved
3782 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3784 t->basetexture = r_texture_white;
3785 t->specularscale = 0;
3788 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3789 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3790 // submodels are biased to avoid z-fighting with world surfaces that they
3791 // may be exactly overlapping (avoids z-fighting artifacts on certain
3792 // doors and things in Quake maps)
3793 if (ent->model->brush.submodel)
3795 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3796 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3799 VectorClear(t->dlightcolor);
3800 t->currentnumlayers = 0;
3801 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3803 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3805 int blendfunc1, blendfunc2, depthmask;
3806 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3808 blendfunc1 = GL_SRC_ALPHA;
3809 blendfunc2 = GL_ONE;
3811 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3813 blendfunc1 = GL_SRC_ALPHA;
3814 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3816 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3818 blendfunc1 = t->customblendfunc[0];
3819 blendfunc2 = t->customblendfunc[1];
3823 blendfunc1 = GL_ONE;
3824 blendfunc2 = GL_ZERO;
3826 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3827 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3829 rtexture_t *currentbasetexture;
3831 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3832 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3833 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3834 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3836 // fullbright is not affected by r_refdef.lightmapintensity
3837 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3838 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3839 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);
3840 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3841 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);
3846 // set the color tint used for lights affecting this surface
3847 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3849 // q3bsp has no lightmap updates, so the lightstylevalue that
3850 // would normally be baked into the lightmap must be
3851 // applied to the color
3852 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
3853 if (ent->model->type == mod_brushq3)
3854 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3855 colorscale *= r_refdef.lightmapintensity;
3856 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);
3857 if (r_ambient.value >= (1.0f/64.0f))
3858 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);
3859 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3861 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);
3862 if (r_ambient.value >= (1.0f/64.0f))
3863 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);
3865 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3867 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);
3868 if (r_ambient.value >= (1.0f/64.0f))
3869 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);
3872 if (t->currentskinframe->glow != NULL)
3873 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);
3874 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3876 // if this is opaque use alpha blend which will darken the earlier
3879 // if this is an alpha blended material, all the earlier passes
3880 // were darkened by fog already, so we only need to add the fog
3881 // color ontop through the fog mask texture
3883 // if this is an additive blended material, all the earlier passes
3884 // were darkened by fog already, and we should not add fog color
3885 // (because the background was not darkened, there is no fog color
3886 // that was lost behind it).
3887 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);
3894 void R_UpdateAllTextureInfo(entity_render_t *ent)
3898 for (i = 0;i < ent->model->num_texturesperskin;i++)
3899 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3902 rsurfacestate_t rsurface;
3904 void R_Mesh_ResizeArrays(int newvertices)
3907 if (rsurface.array_size >= newvertices)
3909 if (rsurface.array_modelvertex3f)
3910 Mem_Free(rsurface.array_modelvertex3f);
3911 rsurface.array_size = (newvertices + 1023) & ~1023;
3912 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3913 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3914 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3915 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3916 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3917 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3918 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3919 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
3920 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
3921 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
3922 rsurface.array_color4f = base + rsurface.array_size * 27;
3923 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
3926 void RSurf_CleanUp(void)
3929 if (rsurface.mode == RSURFMODE_GLSL)
3931 qglUseProgramObjectARB(0);CHECKGLERROR
3933 GL_AlphaTest(false);
3934 rsurface.mode = RSURFMODE_NONE;
3935 rsurface.uselightmaptexture = false;
3936 rsurface.texture = NULL;
3939 void RSurf_ActiveWorldEntity(void)
3941 model_t *model = r_refdef.worldmodel;
3943 if (rsurface.array_size < model->surfmesh.num_vertices)
3944 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
3945 rsurface.matrix = identitymatrix;
3946 rsurface.inversematrix = identitymatrix;
3947 R_Mesh_Matrix(&identitymatrix);
3948 VectorCopy(r_view.origin, rsurface.modelorg);
3949 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
3950 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
3951 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
3952 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
3953 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
3954 rsurface.frameblend[0].frame = 0;
3955 rsurface.frameblend[0].lerp = 1;
3956 rsurface.frameblend[1].frame = 0;
3957 rsurface.frameblend[1].lerp = 0;
3958 rsurface.frameblend[2].frame = 0;
3959 rsurface.frameblend[2].lerp = 0;
3960 rsurface.frameblend[3].frame = 0;
3961 rsurface.frameblend[3].lerp = 0;
3962 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
3963 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
3964 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
3965 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
3966 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
3967 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
3968 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
3969 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
3970 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
3971 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
3972 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
3973 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
3974 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
3975 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
3976 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
3977 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
3978 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
3979 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
3980 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
3981 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
3982 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
3983 rsurface.modelelement3i = model->surfmesh.data_element3i;
3984 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
3985 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
3986 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
3987 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
3988 rsurface.modelsurfaces = model->data_surfaces;
3989 rsurface.generatedvertex = false;
3990 rsurface.vertex3f = rsurface.modelvertex3f;
3991 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
3992 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
3993 rsurface.svector3f = rsurface.modelsvector3f;
3994 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
3995 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
3996 rsurface.tvector3f = rsurface.modeltvector3f;
3997 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
3998 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
3999 rsurface.normal3f = rsurface.modelnormal3f;
4000 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4001 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4002 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4005 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4007 model_t *model = ent->model;
4009 if (rsurface.array_size < model->surfmesh.num_vertices)
4010 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4011 rsurface.matrix = ent->matrix;
4012 rsurface.inversematrix = ent->inversematrix;
4013 R_Mesh_Matrix(&rsurface.matrix);
4014 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4015 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4016 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4017 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4018 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4019 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4020 rsurface.frameblend[0] = ent->frameblend[0];
4021 rsurface.frameblend[1] = ent->frameblend[1];
4022 rsurface.frameblend[2] = ent->frameblend[2];
4023 rsurface.frameblend[3] = ent->frameblend[3];
4024 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4028 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4029 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4030 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4031 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4032 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4034 else if (wantnormals)
4036 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4037 rsurface.modelsvector3f = NULL;
4038 rsurface.modeltvector3f = NULL;
4039 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4040 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4044 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4045 rsurface.modelsvector3f = NULL;
4046 rsurface.modeltvector3f = NULL;
4047 rsurface.modelnormal3f = NULL;
4048 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4050 rsurface.modelvertex3f_bufferobject = 0;
4051 rsurface.modelvertex3f_bufferoffset = 0;
4052 rsurface.modelsvector3f_bufferobject = 0;
4053 rsurface.modelsvector3f_bufferoffset = 0;
4054 rsurface.modeltvector3f_bufferobject = 0;
4055 rsurface.modeltvector3f_bufferoffset = 0;
4056 rsurface.modelnormal3f_bufferobject = 0;
4057 rsurface.modelnormal3f_bufferoffset = 0;
4058 rsurface.generatedvertex = true;
4062 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4063 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4064 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4065 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4066 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4067 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4068 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4069 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4070 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4071 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4072 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4073 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4074 rsurface.generatedvertex = false;
4076 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4077 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4078 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4079 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4080 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4081 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4082 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4083 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4084 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4085 rsurface.modelelement3i = model->surfmesh.data_element3i;
4086 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4087 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4088 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4089 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4090 rsurface.modelsurfaces = model->data_surfaces;
4091 rsurface.vertex3f = rsurface.modelvertex3f;
4092 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4093 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4094 rsurface.svector3f = rsurface.modelsvector3f;
4095 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4096 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4097 rsurface.tvector3f = rsurface.modeltvector3f;
4098 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4099 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4100 rsurface.normal3f = rsurface.modelnormal3f;
4101 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4102 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4103 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4106 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4107 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4110 int texturesurfaceindex;
4115 const float *v1, *in_tc;
4117 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4119 q3shaderinfo_deform_t *deform;
4120 // 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
4121 if (rsurface.generatedvertex)
4123 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4124 generatenormals = true;
4125 for (i = 0;i < Q3MAXDEFORMS;i++)
4127 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4129 generatetangents = true;
4130 generatenormals = true;
4132 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4133 generatenormals = true;
4135 if (generatenormals && !rsurface.modelnormal3f)
4137 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4138 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4139 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4140 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4142 if (generatetangents && !rsurface.modelsvector3f)
4144 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4145 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4146 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4147 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4148 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4149 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4150 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);
4153 rsurface.vertex3f = rsurface.modelvertex3f;
4154 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4155 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4156 rsurface.svector3f = rsurface.modelsvector3f;
4157 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4158 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4159 rsurface.tvector3f = rsurface.modeltvector3f;
4160 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4161 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4162 rsurface.normal3f = rsurface.modelnormal3f;
4163 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4164 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4165 // if vertices are deformed (sprite flares and things in maps, possibly
4166 // water waves, bulges and other deformations), generate them into
4167 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4168 // (may be static model data or generated data for an animated model, or
4169 // the previous deform pass)
4170 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4172 switch (deform->deform)
4175 case Q3DEFORM_PROJECTIONSHADOW:
4176 case Q3DEFORM_TEXT0:
4177 case Q3DEFORM_TEXT1:
4178 case Q3DEFORM_TEXT2:
4179 case Q3DEFORM_TEXT3:
4180 case Q3DEFORM_TEXT4:
4181 case Q3DEFORM_TEXT5:
4182 case Q3DEFORM_TEXT6:
4183 case Q3DEFORM_TEXT7:
4186 case Q3DEFORM_AUTOSPRITE:
4187 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4188 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4189 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4190 VectorNormalize(newforward);
4191 VectorNormalize(newright);
4192 VectorNormalize(newup);
4193 // make deformed versions of only the model vertices used by the specified surfaces
4194 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4196 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4197 // a single autosprite surface can contain multiple sprites...
4198 for (j = 0;j < surface->num_vertices - 3;j += 4)
4200 VectorClear(center);
4201 for (i = 0;i < 4;i++)
4202 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4203 VectorScale(center, 0.25f, center);
4204 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4205 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4206 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4207 for (i = 0;i < 4;i++)
4209 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4210 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4213 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);
4214 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);
4216 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4217 rsurface.vertex3f_bufferobject = 0;
4218 rsurface.vertex3f_bufferoffset = 0;
4219 rsurface.svector3f = rsurface.array_deformedsvector3f;
4220 rsurface.svector3f_bufferobject = 0;
4221 rsurface.svector3f_bufferoffset = 0;
4222 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4223 rsurface.tvector3f_bufferobject = 0;
4224 rsurface.tvector3f_bufferoffset = 0;
4225 rsurface.normal3f = rsurface.array_deformednormal3f;
4226 rsurface.normal3f_bufferobject = 0;
4227 rsurface.normal3f_bufferoffset = 0;
4229 case Q3DEFORM_AUTOSPRITE2:
4230 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4231 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4232 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4233 VectorNormalize(newforward);
4234 VectorNormalize(newright);
4235 VectorNormalize(newup);
4236 // make deformed versions of only the model vertices used by the specified surfaces
4237 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4239 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4240 const float *v1, *v2;
4250 memset(shortest, 0, sizeof(shortest));
4251 // a single autosprite surface can contain multiple sprites...
4252 for (j = 0;j < surface->num_vertices - 3;j += 4)
4254 VectorClear(center);
4255 for (i = 0;i < 4;i++)
4256 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4257 VectorScale(center, 0.25f, center);
4258 // find the two shortest edges, then use them to define the
4259 // axis vectors for rotating around the central axis
4260 for (i = 0;i < 6;i++)
4262 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4263 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4265 Debug_PolygonBegin(NULL, 0, false, 0);
4266 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4267 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);
4268 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4271 l = VectorDistance2(v1, v2);
4272 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4274 l += (1.0f / 1024.0f);
4275 if (shortest[0].length2 > l || i == 0)
4277 shortest[1] = shortest[0];
4278 shortest[0].length2 = l;
4279 shortest[0].v1 = v1;
4280 shortest[0].v2 = v2;
4282 else if (shortest[1].length2 > l || i == 1)
4284 shortest[1].length2 = l;
4285 shortest[1].v1 = v1;
4286 shortest[1].v2 = v2;
4289 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4290 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4292 Debug_PolygonBegin(NULL, 0, false, 0);
4293 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4294 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);
4295 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4298 // this calculates the right vector from the shortest edge
4299 // and the up vector from the edge midpoints
4300 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4301 VectorNormalize(right);
4302 VectorSubtract(end, start, up);
4303 VectorNormalize(up);
4304 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4305 //VectorSubtract(rsurface.modelorg, center, forward);
4306 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4307 VectorNegate(forward, forward);
4308 VectorReflect(forward, 0, up, forward);
4309 VectorNormalize(forward);
4310 CrossProduct(up, forward, newright);
4311 VectorNormalize(newright);
4313 Debug_PolygonBegin(NULL, 0, false, 0);
4314 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);
4315 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4316 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4320 Debug_PolygonBegin(NULL, 0, false, 0);
4321 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4322 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4323 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4326 // rotate the quad around the up axis vector, this is made
4327 // especially easy by the fact we know the quad is flat,
4328 // so we only have to subtract the center position and
4329 // measure distance along the right vector, and then
4330 // multiply that by the newright vector and add back the
4332 // we also need to subtract the old position to undo the
4333 // displacement from the center, which we do with a
4334 // DotProduct, the subtraction/addition of center is also
4335 // optimized into DotProducts here
4336 l = DotProduct(right, center);
4337 for (i = 0;i < 4;i++)
4339 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4340 f = DotProduct(right, v1) - l;
4341 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4344 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);
4345 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);
4347 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4348 rsurface.vertex3f_bufferobject = 0;
4349 rsurface.vertex3f_bufferoffset = 0;
4350 rsurface.svector3f = rsurface.array_deformedsvector3f;
4351 rsurface.svector3f_bufferobject = 0;
4352 rsurface.svector3f_bufferoffset = 0;
4353 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4354 rsurface.tvector3f_bufferobject = 0;
4355 rsurface.tvector3f_bufferoffset = 0;
4356 rsurface.normal3f = rsurface.array_deformednormal3f;
4357 rsurface.normal3f_bufferobject = 0;
4358 rsurface.normal3f_bufferoffset = 0;
4360 case Q3DEFORM_NORMAL:
4361 // deform the normals to make reflections wavey
4362 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4364 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4365 for (j = 0;j < surface->num_vertices;j++)
4368 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4369 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4370 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4371 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4372 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4373 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4374 VectorNormalize(normal);
4376 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);
4378 rsurface.svector3f = rsurface.array_deformedsvector3f;
4379 rsurface.svector3f_bufferobject = 0;
4380 rsurface.svector3f_bufferoffset = 0;
4381 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4382 rsurface.tvector3f_bufferobject = 0;
4383 rsurface.tvector3f_bufferoffset = 0;
4384 rsurface.normal3f = rsurface.array_deformednormal3f;
4385 rsurface.normal3f_bufferobject = 0;
4386 rsurface.normal3f_bufferoffset = 0;
4389 // deform vertex array to make wavey water and flags and such
4390 waveparms[0] = deform->waveparms[0];
4391 waveparms[1] = deform->waveparms[1];
4392 waveparms[2] = deform->waveparms[2];
4393 waveparms[3] = deform->waveparms[3];
4394 // this is how a divisor of vertex influence on deformation
4395 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4396 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4397 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4399 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4400 for (j = 0;j < surface->num_vertices;j++)
4402 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4403 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4404 // if the wavefunc depends on time, evaluate it per-vertex
4407 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4408 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4410 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4413 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4414 rsurface.vertex3f_bufferobject = 0;
4415 rsurface.vertex3f_bufferoffset = 0;
4417 case Q3DEFORM_BULGE:
4418 // deform vertex array to make the surface have moving bulges
4419 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4421 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4422 for (j = 0;j < surface->num_vertices;j++)
4424 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4425 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4428 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4429 rsurface.vertex3f_bufferobject = 0;
4430 rsurface.vertex3f_bufferoffset = 0;
4433 // deform vertex array
4434 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4435 VectorScale(deform->parms, scale, waveparms);
4436 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4438 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4439 for (j = 0;j < surface->num_vertices;j++)
4440 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4442 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4443 rsurface.vertex3f_bufferobject = 0;
4444 rsurface.vertex3f_bufferoffset = 0;
4448 // generate texcoords based on the chosen texcoord source
4449 switch(rsurface.texture->tcgen.tcgen)
4452 case Q3TCGEN_TEXTURE:
4453 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4454 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4455 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4457 case Q3TCGEN_LIGHTMAP:
4458 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4459 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4460 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4462 case Q3TCGEN_VECTOR:
4463 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4465 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4466 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)
4468 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4469 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4472 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4473 rsurface.texcoordtexture2f_bufferobject = 0;
4474 rsurface.texcoordtexture2f_bufferoffset = 0;
4476 case Q3TCGEN_ENVIRONMENT:
4477 // make environment reflections using a spheremap
4478 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4480 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4481 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4482 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4483 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4484 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4486 float l, d, eyedir[3];
4487 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4488 l = 0.5f / VectorLength(eyedir);
4489 d = DotProduct(normal, eyedir)*2;
4490 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4491 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4494 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4495 rsurface.texcoordtexture2f_bufferobject = 0;
4496 rsurface.texcoordtexture2f_bufferoffset = 0;
4499 // the only tcmod that needs software vertex processing is turbulent, so
4500 // check for it here and apply the changes if needed
4501 // and we only support that as the first one
4502 // (handling a mixture of turbulent and other tcmods would be problematic
4503 // without punting it entirely to a software path)
4504 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4506 amplitude = rsurface.texture->tcmods[0].parms[1];
4507 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4508 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4510 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4511 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)
4513 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4514 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4517 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4518 rsurface.texcoordtexture2f_bufferobject = 0;
4519 rsurface.texcoordtexture2f_bufferoffset = 0;
4521 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4522 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4523 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4524 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4527 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4530 const msurface_t *surface = texturesurfacelist[0];
4531 const msurface_t *surface2;
4536 // TODO: lock all array ranges before render, rather than on each surface
4537 if (texturenumsurfaces == 1)
4539 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4540 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));
4542 else if (r_batchmode.integer == 2)
4544 #define MAXBATCHTRIANGLES 4096
4545 int batchtriangles = 0;
4546 int batchelements[MAXBATCHTRIANGLES*3];
4547 for (i = 0;i < texturenumsurfaces;i = j)
4549 surface = texturesurfacelist[i];
4551 if (surface->num_triangles > MAXBATCHTRIANGLES)
4553 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));
4556 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4557 batchtriangles = surface->num_triangles;
4558 firstvertex = surface->num_firstvertex;
4559 endvertex = surface->num_firstvertex + surface->num_vertices;
4560 for (;j < texturenumsurfaces;j++)
4562 surface2 = texturesurfacelist[j];
4563 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4565 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4566 batchtriangles += surface2->num_triangles;
4567 firstvertex = min(firstvertex, surface2->num_firstvertex);
4568 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4570 surface2 = texturesurfacelist[j-1];
4571 numvertices = endvertex - firstvertex;
4572 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4575 else if (r_batchmode.integer == 1)
4577 for (i = 0;i < texturenumsurfaces;i = j)
4579 surface = texturesurfacelist[i];
4580 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4581 if (texturesurfacelist[j] != surface2)
4583 surface2 = texturesurfacelist[j-1];
4584 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4585 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4586 GL_LockArrays(surface->num_firstvertex, numvertices);
4587 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4592 for (i = 0;i < texturenumsurfaces;i++)
4594 surface = texturesurfacelist[i];
4595 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4596 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));
4601 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4603 int i, planeindex, vertexindex;
4607 r_waterstate_waterplane_t *p, *bestp;
4608 msurface_t *surface;
4609 if (r_waterstate.renderingscene)
4611 for (i = 0;i < texturenumsurfaces;i++)
4613 surface = texturesurfacelist[i];
4614 if (lightmaptexunit >= 0)
4615 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4616 if (deluxemaptexunit >= 0)
4617 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4618 // pick the closest matching water plane
4621 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4624 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4626 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4627 d += fabs(PlaneDiff(vert, &p->plane));
4629 if (bestd > d || !bestp)
4637 if (refractiontexunit >= 0)
4638 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4639 if (reflectiontexunit >= 0)
4640 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4644 if (refractiontexunit >= 0)
4645 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4646 if (reflectiontexunit >= 0)
4647 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4649 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4650 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));
4654 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4658 const msurface_t *surface = texturesurfacelist[0];
4659 const msurface_t *surface2;
4664 // TODO: lock all array ranges before render, rather than on each surface
4665 if (texturenumsurfaces == 1)
4667 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4668 if (deluxemaptexunit >= 0)
4669 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4670 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4671 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));
4673 else if (r_batchmode.integer == 2)
4675 #define MAXBATCHTRIANGLES 4096
4676 int batchtriangles = 0;
4677 int batchelements[MAXBATCHTRIANGLES*3];
4678 for (i = 0;i < texturenumsurfaces;i = j)
4680 surface = texturesurfacelist[i];
4681 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4682 if (deluxemaptexunit >= 0)
4683 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4685 if (surface->num_triangles > MAXBATCHTRIANGLES)
4687 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));
4690 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4691 batchtriangles = surface->num_triangles;
4692 firstvertex = surface->num_firstvertex;
4693 endvertex = surface->num_firstvertex + surface->num_vertices;
4694 for (;j < texturenumsurfaces;j++)
4696 surface2 = texturesurfacelist[j];
4697 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4699 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4700 batchtriangles += surface2->num_triangles;
4701 firstvertex = min(firstvertex, surface2->num_firstvertex);
4702 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4704 surface2 = texturesurfacelist[j-1];
4705 numvertices = endvertex - firstvertex;
4706 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4709 else if (r_batchmode.integer == 1)
4712 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4713 for (i = 0;i < texturenumsurfaces;i = j)
4715 surface = texturesurfacelist[i];
4716 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4717 if (texturesurfacelist[j] != surface2)
4719 Con_Printf(" %i", j - i);
4722 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4724 for (i = 0;i < texturenumsurfaces;i = j)
4726 surface = texturesurfacelist[i];
4727 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4728 if (deluxemaptexunit >= 0)
4729 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4730 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4731 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4734 Con_Printf(" %i", j - i);
4736 surface2 = texturesurfacelist[j-1];
4737 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4738 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4739 GL_LockArrays(surface->num_firstvertex, numvertices);
4740 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4748 for (i = 0;i < texturenumsurfaces;i++)
4750 surface = texturesurfacelist[i];
4751 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4752 if (deluxemaptexunit >= 0)
4753 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4754 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4755 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));
4760 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4763 int texturesurfaceindex;
4764 if (r_showsurfaces.integer == 2)
4766 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4768 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4769 for (j = 0;j < surface->num_triangles;j++)
4771 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4772 GL_Color(f, f, f, 1);
4773 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)));
4779 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4781 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4782 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4783 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);
4784 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4785 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));
4790 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4792 int texturesurfaceindex;
4796 if (rsurface.lightmapcolor4f)
4798 // generate color arrays for the surfaces in this list
4799 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4801 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4802 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)
4804 f = FogPoint_Model(v);
4814 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4816 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4817 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)
4819 f = FogPoint_Model(v);
4827 rsurface.lightmapcolor4f = rsurface.array_color4f;
4828 rsurface.lightmapcolor4f_bufferobject = 0;
4829 rsurface.lightmapcolor4f_bufferoffset = 0;
4832 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4834 int texturesurfaceindex;
4837 if (!rsurface.lightmapcolor4f)
4839 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4841 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4842 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)
4850 rsurface.lightmapcolor4f = rsurface.array_color4f;
4851 rsurface.lightmapcolor4f_bufferobject = 0;
4852 rsurface.lightmapcolor4f_bufferoffset = 0;
4855 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4858 rsurface.lightmapcolor4f = NULL;
4859 rsurface.lightmapcolor4f_bufferobject = 0;
4860 rsurface.lightmapcolor4f_bufferoffset = 0;
4861 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4862 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4863 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4864 GL_Color(r, g, b, a);
4865 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4868 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4870 // TODO: optimize applyfog && applycolor case
4871 // just apply fog if necessary, and tint the fog color array if necessary
4872 rsurface.lightmapcolor4f = NULL;
4873 rsurface.lightmapcolor4f_bufferobject = 0;
4874 rsurface.lightmapcolor4f_bufferoffset = 0;
4875 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4876 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4877 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4878 GL_Color(r, g, b, a);
4879 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4882 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4884 int texturesurfaceindex;
4888 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4890 // generate color arrays for the surfaces in this list
4891 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4893 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4894 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4896 if (surface->lightmapinfo->samples)
4898 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4899 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4900 VectorScale(lm, scale, c);
4901 if (surface->lightmapinfo->styles[1] != 255)
4903 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4905 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4906 VectorMA(c, scale, lm, c);
4907 if (surface->lightmapinfo->styles[2] != 255)
4910 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4911 VectorMA(c, scale, lm, c);
4912 if (surface->lightmapinfo->styles[3] != 255)
4915 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4916 VectorMA(c, scale, lm, c);
4926 rsurface.lightmapcolor4f = rsurface.array_color4f;
4927 rsurface.lightmapcolor4f_bufferobject = 0;
4928 rsurface.lightmapcolor4f_bufferoffset = 0;
4932 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
4933 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
4934 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
4936 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4937 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4938 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4939 GL_Color(r, g, b, a);
4940 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4943 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4945 int texturesurfaceindex;
4949 vec3_t ambientcolor;
4950 vec3_t diffusecolor;
4954 VectorCopy(rsurface.modellight_lightdir, lightdir);
4955 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
4956 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
4957 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
4958 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
4959 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
4960 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
4961 if (VectorLength2(diffusecolor) > 0)
4963 // generate color arrays for the surfaces in this list
4964 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4966 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4967 int numverts = surface->num_vertices;
4968 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
4969 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
4970 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
4971 // q3-style directional shading
4972 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
4974 if ((f = DotProduct(c2, lightdir)) > 0)
4975 VectorMA(ambientcolor, f, diffusecolor, c);
4977 VectorCopy(ambientcolor, c);
4986 rsurface.lightmapcolor4f = rsurface.array_color4f;
4987 rsurface.lightmapcolor4f_bufferobject = 0;
4988 rsurface.lightmapcolor4f_bufferoffset = 0;
4992 r = ambientcolor[0];
4993 g = ambientcolor[1];
4994 b = ambientcolor[2];
4995 rsurface.lightmapcolor4f = NULL;
4996 rsurface.lightmapcolor4f_bufferobject = 0;
4997 rsurface.lightmapcolor4f_bufferoffset = 0;
4999 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5000 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5001 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5002 GL_Color(r, g, b, a);
5003 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5006 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5008 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5009 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5010 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5011 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5012 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5014 rsurface.mode = RSURFMODE_SHOWSURFACES;
5016 GL_BlendFunc(GL_ONE, GL_ZERO);
5017 R_Mesh_ColorPointer(NULL, 0, 0);
5018 R_Mesh_ResetTextureState();
5020 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5021 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5024 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5026 // transparent sky would be ridiculous
5027 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5029 if (rsurface.mode != RSURFMODE_SKY)
5031 if (rsurface.mode == RSURFMODE_GLSL)
5033 qglUseProgramObjectARB(0);CHECKGLERROR
5035 rsurface.mode = RSURFMODE_SKY;
5039 skyrendernow = false;
5041 // restore entity matrix
5042 R_Mesh_Matrix(&rsurface.matrix);
5044 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5045 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5046 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5047 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5049 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5050 // skymasking on them, and Quake3 never did sky masking (unlike
5051 // software Quake and software Quake2), so disable the sky masking
5052 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5053 // and skymasking also looks very bad when noclipping outside the
5054 // level, so don't use it then either.
5055 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5057 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5058 R_Mesh_ColorPointer(NULL, 0, 0);
5059 R_Mesh_ResetTextureState();
5060 if (skyrendermasked)
5062 // depth-only (masking)
5063 GL_ColorMask(0,0,0,0);
5064 // just to make sure that braindead drivers don't draw
5065 // anything despite that colormask...
5066 GL_BlendFunc(GL_ZERO, GL_ONE);
5071 GL_BlendFunc(GL_ONE, GL_ZERO);
5073 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5074 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5075 if (skyrendermasked)
5076 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5080 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5082 if (rsurface.mode != RSURFMODE_GLSL)
5084 rsurface.mode = RSURFMODE_GLSL;
5085 R_Mesh_ResetTextureState();
5088 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5089 if (!r_glsl_permutation)
5092 if (rsurface.lightmode == 2)
5093 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5095 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5096 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5097 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5098 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5099 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5100 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5102 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]);
5103 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5105 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5106 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5107 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5108 R_Mesh_ColorPointer(NULL, 0, 0);
5110 else if (rsurface.uselightmaptexture)
5112 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5113 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5114 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5115 R_Mesh_ColorPointer(NULL, 0, 0);
5119 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5120 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5121 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5122 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5125 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5127 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5128 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);
5130 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5134 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5135 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);
5137 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5139 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5144 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5146 // OpenGL 1.3 path - anything not completely ancient
5147 int texturesurfaceindex;
5148 qboolean applycolor;
5152 const texturelayer_t *layer;
5153 if (rsurface.mode != RSURFMODE_MULTIPASS)
5154 rsurface.mode = RSURFMODE_MULTIPASS;
5155 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5156 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5159 int layertexrgbscale;
5160 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5162 if (layerindex == 0)
5166 GL_AlphaTest(false);
5167 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5170 GL_DepthMask(layer->depthmask);
5171 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5172 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5174 layertexrgbscale = 4;
5175 VectorScale(layer->color, 0.25f, layercolor);
5177 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5179 layertexrgbscale = 2;
5180 VectorScale(layer->color, 0.5f, layercolor);
5184 layertexrgbscale = 1;
5185 VectorScale(layer->color, 1.0f, layercolor);
5187 layercolor[3] = layer->color[3];
5188 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5189 R_Mesh_ColorPointer(NULL, 0, 0);
5190 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5191 switch (layer->type)
5193 case TEXTURELAYERTYPE_LITTEXTURE:
5194 memset(&m, 0, sizeof(m));
5195 m.tex[0] = R_GetTexture(r_texture_white);
5196 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5197 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5198 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5199 m.tex[1] = R_GetTexture(layer->texture);
5200 m.texmatrix[1] = layer->texmatrix;
5201 m.texrgbscale[1] = layertexrgbscale;
5202 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5203 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5204 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5205 R_Mesh_TextureState(&m);
5206 if (rsurface.lightmode == 2)
5207 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5208 else if (rsurface.uselightmaptexture)
5209 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5211 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5213 case TEXTURELAYERTYPE_TEXTURE:
5214 memset(&m, 0, sizeof(m));
5215 m.tex[0] = R_GetTexture(layer->texture);
5216 m.texmatrix[0] = layer->texmatrix;
5217 m.texrgbscale[0] = layertexrgbscale;
5218 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5219 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5220 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5221 R_Mesh_TextureState(&m);
5222 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5224 case TEXTURELAYERTYPE_FOG:
5225 memset(&m, 0, sizeof(m));
5226 m.texrgbscale[0] = layertexrgbscale;
5229 m.tex[0] = R_GetTexture(layer->texture);
5230 m.texmatrix[0] = layer->texmatrix;
5231 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5232 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5233 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5235 R_Mesh_TextureState(&m);
5236 // generate a color array for the fog pass
5237 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5238 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5242 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5243 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)
5245 f = 1 - FogPoint_Model(v);
5246 c[0] = layercolor[0];
5247 c[1] = layercolor[1];
5248 c[2] = layercolor[2];
5249 c[3] = f * layercolor[3];
5252 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5255 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5257 GL_LockArrays(0, 0);
5260 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5262 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5263 GL_AlphaTest(false);
5267 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5269 // OpenGL 1.1 - crusty old voodoo path
5270 int texturesurfaceindex;
5274 const texturelayer_t *layer;
5275 if (rsurface.mode != RSURFMODE_MULTIPASS)
5276 rsurface.mode = RSURFMODE_MULTIPASS;
5277 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5278 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5282 if (layerindex == 0)
5286 GL_AlphaTest(false);
5287 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5290 GL_DepthMask(layer->depthmask);
5291 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5292 R_Mesh_ColorPointer(NULL, 0, 0);
5293 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5294 switch (layer->type)
5296 case TEXTURELAYERTYPE_LITTEXTURE:
5297 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5299 // two-pass lit texture with 2x rgbscale
5300 // first the lightmap pass
5301 memset(&m, 0, sizeof(m));
5302 m.tex[0] = R_GetTexture(r_texture_white);
5303 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5304 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5305 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5306 R_Mesh_TextureState(&m);
5307 if (rsurface.lightmode == 2)
5308 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5309 else if (rsurface.uselightmaptexture)
5310 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5312 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5313 GL_LockArrays(0, 0);
5314 // then apply the texture to it
5315 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5316 memset(&m, 0, sizeof(m));
5317 m.tex[0] = R_GetTexture(layer->texture);
5318 m.texmatrix[0] = layer->texmatrix;
5319 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5320 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5321 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5322 R_Mesh_TextureState(&m);
5323 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);
5327 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5328 memset(&m, 0, sizeof(m));
5329 m.tex[0] = R_GetTexture(layer->texture);
5330 m.texmatrix[0] = layer->texmatrix;
5331 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5332 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5333 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5334 R_Mesh_TextureState(&m);
5335 if (rsurface.lightmode == 2)
5336 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);
5338 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);
5341 case TEXTURELAYERTYPE_TEXTURE:
5342 // singletexture unlit texture with transparency support
5343 memset(&m, 0, sizeof(m));
5344 m.tex[0] = R_GetTexture(layer->texture);
5345 m.texmatrix[0] = layer->texmatrix;
5346 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5347 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5348 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5349 R_Mesh_TextureState(&m);
5350 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);
5352 case TEXTURELAYERTYPE_FOG:
5353 // singletexture fogging
5354 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5357 memset(&m, 0, sizeof(m));
5358 m.tex[0] = R_GetTexture(layer->texture);
5359 m.texmatrix[0] = layer->texmatrix;
5360 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5361 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5362 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5363 R_Mesh_TextureState(&m);
5366 R_Mesh_ResetTextureState();
5367 // generate a color array for the fog pass
5368 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5372 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5373 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)
5375 f = 1 - FogPoint_Model(v);
5376 c[0] = layer->color[0];
5377 c[1] = layer->color[1];
5378 c[2] = layer->color[2];
5379 c[3] = f * layer->color[3];
5382 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5385 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5387 GL_LockArrays(0, 0);
5390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5392 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5393 GL_AlphaTest(false);
5397 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5401 rsurface.rtlight = NULL;
5405 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5407 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER))
5409 if (rsurface.mode != RSURFMODE_MULTIPASS)
5410 rsurface.mode = RSURFMODE_MULTIPASS;
5411 if (r_depthfirst.integer == 3)
5413 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5414 if (!r_view.showdebug)
5415 GL_Color(0, 0, 0, 1);
5417 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5421 GL_ColorMask(0,0,0,0);
5424 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5425 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5426 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5428 GL_BlendFunc(GL_ONE, GL_ZERO);
5430 GL_AlphaTest(false);
5431 R_Mesh_ColorPointer(NULL, 0, 0);
5432 R_Mesh_ResetTextureState();
5433 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5434 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5435 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5436 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5438 else if (r_depthfirst.integer == 3)
5440 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5442 GL_Color(0, 0, 0, 1);
5443 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5445 else if (r_showsurfaces.integer)
5447 if (rsurface.mode != RSURFMODE_MULTIPASS)
5448 rsurface.mode = RSURFMODE_MULTIPASS;
5449 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5450 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5452 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5453 GL_BlendFunc(GL_ONE, GL_ZERO);
5454 GL_DepthMask(writedepth);
5456 GL_AlphaTest(false);
5457 R_Mesh_ColorPointer(NULL, 0, 0);
5458 R_Mesh_ResetTextureState();
5459 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5460 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5461 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5463 else if (gl_lightmaps.integer)
5466 if (rsurface.mode != RSURFMODE_MULTIPASS)
5467 rsurface.mode = RSURFMODE_MULTIPASS;
5468 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5470 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5471 GL_BlendFunc(GL_ONE, GL_ZERO);
5472 GL_DepthMask(writedepth);
5474 GL_AlphaTest(false);
5475 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5476 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5477 R_Mesh_ColorPointer(NULL, 0, 0);
5478 memset(&m, 0, sizeof(m));
5479 m.tex[0] = R_GetTexture(r_texture_white);
5480 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5481 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5482 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5483 R_Mesh_TextureState(&m);
5484 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5485 if (rsurface.lightmode == 2)
5486 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5487 else if (rsurface.uselightmaptexture)
5488 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5490 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5491 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5493 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5495 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5496 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5498 else if (rsurface.texture->currentnumlayers)
5500 // write depth for anything we skipped on the depth-only pass earlier
5501 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5503 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5504 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5505 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5506 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5507 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5509 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5510 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5511 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5512 if (r_glsl.integer && gl_support_fragment_shader)
5513 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5514 else if (gl_combine.integer && r_textureunits.integer >= 2)
5515 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5517 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5518 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5521 GL_LockArrays(0, 0);
5524 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5527 int texturenumsurfaces, endsurface;
5529 msurface_t *surface;
5530 msurface_t *texturesurfacelist[1024];
5532 // if the model is static it doesn't matter what value we give for
5533 // wantnormals and wanttangents, so this logic uses only rules applicable
5534 // to a model, knowing that they are meaningless otherwise
5535 if (ent == r_refdef.worldentity)
5536 RSurf_ActiveWorldEntity();
5537 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5538 RSurf_ActiveModelEntity(ent, false, false);
5540 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5542 for (i = 0;i < numsurfaces;i = j)
5545 surface = rsurface.modelsurfaces + surfacelist[i];
5546 texture = surface->texture;
5547 R_UpdateTextureInfo(ent, texture);
5548 rsurface.texture = texture->currentframe;
5549 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5550 // scan ahead until we find a different texture
5551 endsurface = min(i + 1024, numsurfaces);
5552 texturenumsurfaces = 0;
5553 texturesurfacelist[texturenumsurfaces++] = surface;
5554 for (;j < endsurface;j++)
5556 surface = rsurface.modelsurfaces + surfacelist[j];
5557 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5559 texturesurfacelist[texturenumsurfaces++] = surface;
5561 // render the range of surfaces
5562 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5568 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5571 vec3_t tempcenter, center;
5573 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5576 for (i = 0;i < numsurfaces;i++)
5577 if (surfacelist[i]->texture->currentframe->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5578 R_Water_AddWaterPlane(surfacelist[i]);
5581 // break the surface list down into batches by texture and use of lightmapping
5582 for (i = 0;i < numsurfaces;i = j)
5585 // texture is the base texture pointer, rsurface.texture is the
5586 // current frame/skin the texture is directing us to use (for example
5587 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5588 // use skin 1 instead)
5589 texture = surfacelist[i]->texture;
5590 rsurface.texture = texture->currentframe;
5591 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5592 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5594 // if this texture is not the kind we want, skip ahead to the next one
5595 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5599 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5601 // transparent surfaces get pushed off into the transparent queue
5602 const msurface_t *surface = surfacelist[i];
5605 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5606 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5607 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5608 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5609 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5613 // simply scan ahead until we find a different texture or lightmap state
5614 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5616 // render the range of surfaces
5617 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5622 float locboxvertex3f[6*4*3] =
5624 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5625 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5626 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5627 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5628 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5629 1,0,0, 0,0,0, 0,1,0, 1,1,0
5632 int locboxelement3i[6*2*3] =
5642 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5645 cl_locnode_t *loc = (cl_locnode_t *)ent;
5647 float vertex3f[6*4*3];
5649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5650 GL_DepthMask(false);
5651 GL_DepthRange(0, 1);
5652 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5654 GL_CullFace(GL_NONE);
5655 R_Mesh_Matrix(&identitymatrix);
5657 R_Mesh_VertexPointer(vertex3f, 0, 0);
5658 R_Mesh_ColorPointer(NULL, 0, 0);
5659 R_Mesh_ResetTextureState();
5662 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5663 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5664 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5665 surfacelist[0] < 0 ? 0.5f : 0.125f);
5667 if (VectorCompare(loc->mins, loc->maxs))
5669 VectorSet(size, 2, 2, 2);
5670 VectorMA(loc->mins, -0.5f, size, mins);
5674 VectorCopy(loc->mins, mins);
5675 VectorSubtract(loc->maxs, loc->mins, size);
5678 for (i = 0;i < 6*4*3;)
5679 for (j = 0;j < 3;j++, i++)
5680 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5682 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5685 void R_DrawLocs(void)
5688 cl_locnode_t *loc, *nearestloc;
5690 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5691 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5693 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5694 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5698 void R_DrawCollisionBrushes(entity_render_t *ent)
5702 msurface_t *surface;
5703 model_t *model = ent->model;
5704 if (!model->brush.num_brushes)
5707 R_Mesh_ColorPointer(NULL, 0, 0);
5708 R_Mesh_ResetTextureState();
5709 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5710 GL_DepthMask(false);
5711 GL_DepthRange(0, 1);
5712 GL_DepthTest(!r_showdisabledepthtest.integer);
5713 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5714 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5715 if (brush->colbrushf && brush->colbrushf->numtriangles)
5716 R_DrawCollisionBrush(brush->colbrushf);
5717 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5718 if (surface->num_collisiontriangles)
5719 R_DrawCollisionSurface(ent, surface);
5720 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5723 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5726 const int *elements;
5727 msurface_t *surface;
5728 model_t *model = ent->model;
5731 GL_DepthRange(0, 1);
5732 GL_DepthTest(!r_showdisabledepthtest.integer);
5733 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5735 GL_BlendFunc(GL_ONE, GL_ZERO);
5736 R_Mesh_ColorPointer(NULL, 0, 0);
5737 R_Mesh_ResetTextureState();
5738 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5740 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5742 rsurface.texture = surface->texture->currentframe;
5743 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5745 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5748 if (!rsurface.texture->currentlayers->depthmask)
5749 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5750 else if (ent == r_refdef.worldentity)
5751 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5753 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5754 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5757 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5759 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5760 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5761 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5762 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5769 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5771 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5773 VectorCopy(rsurface.vertex3f + l * 3, v);
5774 qglVertex3f(v[0], v[1], v[2]);
5775 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5776 qglVertex3f(v[0], v[1], v[2]);
5780 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5782 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5784 VectorCopy(rsurface.vertex3f + l * 3, v);
5785 qglVertex3f(v[0], v[1], v[2]);
5786 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5787 qglVertex3f(v[0], v[1], v[2]);
5791 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5793 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5795 VectorCopy(rsurface.vertex3f + l * 3, v);
5796 qglVertex3f(v[0], v[1], v[2]);
5797 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5798 qglVertex3f(v[0], v[1], v[2]);
5805 rsurface.texture = NULL;
5808 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5809 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5811 int i, j, endj, f, flagsmask;
5812 int counttriangles = 0;
5813 msurface_t *surface, **surfacechain;
5815 model_t *model = r_refdef.worldmodel;
5816 const int maxsurfacelist = 1024;
5817 int numsurfacelist = 0;
5818 msurface_t *surfacelist[1024];
5822 RSurf_ActiveWorldEntity();
5824 // update light styles
5825 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5827 for (i = 0;i < model->brushq1.light_styles;i++)
5829 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5831 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5832 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5833 for (;(surface = *surfacechain);surfacechain++)
5834 surface->cached_dlight = true;
5839 R_UpdateAllTextureInfo(r_refdef.worldentity);
5840 flagsmask = addwaterplanes ? MATERIALFLAG_WATERSHADER : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
5843 rsurface.uselightmaptexture = false;
5844 rsurface.texture = NULL;
5846 j = model->firstmodelsurface;
5847 endj = j + model->nummodelsurfaces;
5850 // quickly skip over non-visible surfaces
5851 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5853 // quickly iterate over visible surfaces
5854 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5856 // process this surface
5857 surface = model->data_surfaces + j;
5858 // if this surface fits the criteria, add it to the list
5859 if (surface->num_triangles)
5861 // if lightmap parameters changed, rebuild lightmap texture
5862 if (surface->cached_dlight)
5863 R_BuildLightMap(r_refdef.worldentity, surface);
5864 // add face to draw list
5865 surfacelist[numsurfacelist++] = surface;
5866 counttriangles += surface->num_triangles;
5867 if (numsurfacelist >= maxsurfacelist)
5869 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5876 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5877 r_refdef.stats.entities_triangles += counttriangles;
5880 if (r_view.showdebug)
5882 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
5883 R_DrawCollisionBrushes(r_refdef.worldentity);
5885 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
5886 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5890 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5892 int i, f, flagsmask;
5893 int counttriangles = 0;
5894 msurface_t *surface, *endsurface, **surfacechain;
5896 model_t *model = ent->model;
5897 const int maxsurfacelist = 1024;
5898 int numsurfacelist = 0;
5899 msurface_t *surfacelist[1024];
5903 // if the model is static it doesn't matter what value we give for
5904 // wantnormals and wanttangents, so this logic uses only rules applicable
5905 // to a model, knowing that they are meaningless otherwise
5906 if (ent == r_refdef.worldentity)
5907 RSurf_ActiveWorldEntity();
5908 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5909 RSurf_ActiveModelEntity(ent, false, false);
5911 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5913 // update light styles
5914 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5916 for (i = 0;i < model->brushq1.light_styles;i++)
5918 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5920 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5921 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5922 for (;(surface = *surfacechain);surfacechain++)
5923 surface->cached_dlight = true;
5928 R_UpdateAllTextureInfo(ent);
5929 flagsmask = addwaterplanes ? MATERIALFLAG_WATERSHADER : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
5932 rsurface.uselightmaptexture = false;
5933 rsurface.texture = NULL;
5935 surface = model->data_surfaces + model->firstmodelsurface;
5936 endsurface = surface + model->nummodelsurfaces;
5937 for (;surface < endsurface;surface++)
5939 // if this surface fits the criteria, add it to the list
5940 if (surface->num_triangles)
5942 // if lightmap parameters changed, rebuild lightmap texture
5943 if (surface->cached_dlight)
5944 R_BuildLightMap(ent, surface);
5945 // add face to draw list
5946 surfacelist[numsurfacelist++] = surface;
5947 counttriangles += surface->num_triangles;
5948 if (numsurfacelist >= maxsurfacelist)
5950 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5956 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5957 r_refdef.stats.entities_triangles += counttriangles;
5960 if (r_view.showdebug)
5962 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
5963 R_DrawCollisionBrushes(ent);
5965 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
5966 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);