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;
157 int materialflags; // combined flags of all water surfaces on this plane
158 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
161 r_waterstate_waterplane_t;
163 #define MAX_WATERPLANES 16
165 static struct r_waterstate_s
169 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
171 int waterwidth, waterheight;
172 int texturewidth, textureheight;
174 int maxwaterplanes; // same as MAX_WATERPLANES
176 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
178 float screenscale[2];
179 float screencenter[2];
183 // shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 //rtexture_t *r_texture_fogintensity;
196 // information about each possible shader permutation
197 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
198 // currently selected permutation
199 r_glsl_permutation_t *r_glsl_permutation;
201 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
202 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
204 // vertex coordinates for a quad that covers the screen exactly
205 const static float r_screenvertex3f[12] =
213 extern void R_DrawModelShadows(void);
215 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
218 for (i = 0;i < verts;i++)
229 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
232 for (i = 0;i < verts;i++)
242 // FIXME: move this to client?
245 if (gamemode == GAME_NEHAHRA)
247 Cvar_Set("gl_fogenable", "0");
248 Cvar_Set("gl_fogdensity", "0.2");
249 Cvar_Set("gl_fogred", "0.3");
250 Cvar_Set("gl_foggreen", "0.3");
251 Cvar_Set("gl_fogblue", "0.3");
253 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
256 float FogPoint_World(const vec3_t p)
258 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
259 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
262 float FogPoint_Model(const vec3_t p)
264 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
265 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
268 static void R_BuildBlankTextures(void)
270 unsigned char data[4];
271 data[0] = 128; // normal X
272 data[1] = 128; // normal Y
273 data[2] = 255; // normal Z
274 data[3] = 128; // height
275 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
285 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
290 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
293 static void R_BuildNoTexture(void)
296 unsigned char pix[16][16][4];
297 // this makes a light grey/dark grey checkerboard texture
298 for (y = 0;y < 16;y++)
300 for (x = 0;x < 16;x++)
302 if ((y < 8) ^ (x < 8))
318 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
321 static void R_BuildWhiteCube(void)
323 unsigned char data[6*1*1*4];
324 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
325 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
326 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
327 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
328 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
329 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
330 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
333 static void R_BuildNormalizationCube(void)
337 vec_t s, t, intensity;
339 unsigned char data[6][NORMSIZE][NORMSIZE][4];
340 for (side = 0;side < 6;side++)
342 for (y = 0;y < NORMSIZE;y++)
344 for (x = 0;x < NORMSIZE;x++)
346 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
347 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 intensity = 127.0f / sqrt(DotProduct(v, v));
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
384 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
386 data[side][y][x][3] = 255;
390 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
393 static void R_BuildFogTexture(void)
397 unsigned char data1[FOGWIDTH][4];
398 //unsigned char data2[FOGWIDTH][4];
399 for (x = 0;x < FOGWIDTH;x++)
401 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
406 //data2[x][0] = 255 - b;
407 //data2[x][1] = 255 - b;
408 //data2[x][2] = 255 - b;
411 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
415 static const char *builtinshaderstring =
416 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
417 "// written by Forest 'LordHavoc' Hale\n"
419 "// common definitions between vertex shader and fragment shader:\n"
421 "#ifdef __GLSL_CG_DATA_TYPES\n"
422 "# define myhalf half\n"
423 "# define myhvec2 hvec2\n"
424 "# define myhvec3 hvec3\n"
425 "# define myhvec4 hvec4\n"
427 "# define myhalf float\n"
428 "# define myhvec2 vec2\n"
429 "# define myhvec3 vec3\n"
430 "# define myhvec4 vec4\n"
433 "varying vec2 TexCoord;\n"
434 "varying vec2 TexCoordLightmap;\n"
436 "//#ifdef MODE_LIGHTSOURCE\n"
437 "varying vec3 CubeVector;\n"
440 "//#ifdef MODE_LIGHTSOURCE\n"
441 "varying vec3 LightVector;\n"
443 "//# ifdef MODE_LIGHTDIRECTION\n"
444 "//varying vec3 LightVector;\n"
448 "varying vec3 EyeVector;\n"
450 "varying vec3 EyeVectorModelSpace;\n"
453 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
454 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
455 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
457 "//#ifdef USEWATER\n"
458 "varying vec4 ModelViewProjectionPosition;\n"
460 "//# ifdef USEREFLECTION\n"
461 "//varying vec4 ModelViewProjectionPosition;\n"
469 "// vertex shader specific:\n"
470 "#ifdef VERTEX_SHADER\n"
472 "uniform vec3 LightPosition;\n"
473 "uniform vec3 EyePosition;\n"
474 "uniform vec3 LightDir;\n"
476 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
480 " gl_FrontColor = gl_Color;\n"
481 " // copy the surface texcoord\n"
482 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
483 "#ifndef MODE_LIGHTSOURCE\n"
484 "# ifndef MODE_LIGHTDIRECTION\n"
485 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
489 "#ifdef MODE_LIGHTSOURCE\n"
490 " // transform vertex position into light attenuation/cubemap space\n"
491 " // (-1 to +1 across the light box)\n"
492 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
494 " // transform unnormalized light direction into tangent space\n"
495 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
496 " // normalize it per pixel)\n"
497 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
498 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
503 "#ifdef MODE_LIGHTDIRECTION\n"
504 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
505 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
506 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
509 " // transform unnormalized eye direction into tangent space\n"
511 " vec3 EyeVectorModelSpace;\n"
513 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
514 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
515 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
516 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
518 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
519 " VectorS = gl_MultiTexCoord1.xyz;\n"
520 " VectorT = gl_MultiTexCoord2.xyz;\n"
521 " VectorR = gl_MultiTexCoord3.xyz;\n"
524 "//#if defined(USEWATER) || defined(USEREFLECTION)\n"
525 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
526 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
527 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
530 "// transform vertex to camera space, using ftransform to match non-VS\n"
532 " gl_Position = ftransform();\n"
535 " ModelViewProjectionPosition = gl_Position;\n"
537 "# ifdef USEREFLECTION\n"
538 " ModelViewProjectionPosition = gl_Position;\n"
543 "#endif // VERTEX_SHADER\n"
548 "// fragment shader specific:\n"
549 "#ifdef FRAGMENT_SHADER\n"
551 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
552 "uniform sampler2D Texture_Normal;\n"
553 "uniform sampler2D Texture_Color;\n"
554 "uniform sampler2D Texture_Gloss;\n"
555 "uniform samplerCube Texture_Cube;\n"
556 "uniform sampler2D Texture_Attenuation;\n"
557 "uniform sampler2D Texture_FogMask;\n"
558 "uniform sampler2D Texture_Pants;\n"
559 "uniform sampler2D Texture_Shirt;\n"
560 "uniform sampler2D Texture_Lightmap;\n"
561 "uniform sampler2D Texture_Deluxemap;\n"
562 "uniform sampler2D Texture_Glow;\n"
563 "uniform sampler2D Texture_Reflection;\n"
564 "uniform sampler2D Texture_Refraction;\n"
566 "uniform myhvec3 LightColor;\n"
567 "uniform myhvec3 AmbientColor;\n"
568 "uniform myhvec3 DiffuseColor;\n"
569 "uniform myhvec3 SpecularColor;\n"
570 "uniform myhvec3 Color_Pants;\n"
571 "uniform myhvec3 Color_Shirt;\n"
572 "uniform myhvec3 FogColor;\n"
574 "//#ifdef USEWATER\n"
575 "uniform vec4 DistortScaleRefractReflect;\n"
576 "uniform vec4 ScreenScaleRefractReflect;\n"
577 "uniform vec4 ScreenCenterRefractReflect;\n"
578 "uniform myhvec3 RefractColor;\n"
579 "uniform myhvec3 ReflectColor;\n"
581 "//# ifdef USEREFLECTION\n"
582 "//uniform vec4 DistortScaleRefractReflect;\n"
583 "//uniform vec4 ScreenScaleRefractReflect;\n"
584 "//uniform vec4 ScreenCenterRefractReflect;\n"
585 "//uniform myhvec3 ReflectColor;\n"
589 "uniform myhalf GlowScale;\n"
590 "uniform myhalf SceneBrightness;\n"
591 "#ifdef USECONTRASTBOOST\n"
592 "uniform myhalf ContrastBoostCoeff;\n"
595 "uniform float OffsetMapping_Scale;\n"
596 "uniform float OffsetMapping_Bias;\n"
597 "uniform float FogRangeRecip;\n"
599 "uniform myhalf AmbientScale;\n"
600 "uniform myhalf DiffuseScale;\n"
601 "uniform myhalf SpecularScale;\n"
602 "uniform myhalf SpecularPower;\n"
604 "#ifdef USEOFFSETMAPPING\n"
605 "vec2 OffsetMapping(vec2 TexCoord)\n"
607 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
608 " // 14 sample relief mapping: linear search and then binary search\n"
609 " // this basically steps forward a small amount repeatedly until it finds\n"
610 " // itself inside solid, then jitters forward and back using decreasing\n"
611 " // amounts to find the impact\n"
612 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
613 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
614 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
615 " vec3 RT = vec3(TexCoord, 1);\n"
616 " OffsetVector *= 0.1;\n"
617 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
618 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
619 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
620 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
621 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
622 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
623 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
624 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
625 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
626 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
627 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
628 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
629 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
630 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
633 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
634 " // this basically moves forward the full distance, and then backs up based\n"
635 " // on height of samples\n"
636 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
637 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
638 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
639 " TexCoord += OffsetVector;\n"
640 " OffsetVector *= 0.333;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
642 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
643 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
644 " return TexCoord;\n"
651 "#ifdef USEOFFSETMAPPING\n"
652 " // apply offsetmapping\n"
653 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
654 "#define TexCoord TexCoordOffset\n"
657 " // combine the diffuse textures (base, pants, shirt)\n"
658 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
659 "#ifdef USECOLORMAPPING\n"
660 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
666 "#ifdef MODE_LIGHTSOURCE\n"
669 " // calculate surface normal, light normal, and specular normal\n"
670 " // compute color intensity for the two textures (colormap and glossmap)\n"
671 " // scale by light color and attenuation as efficiently as possible\n"
672 " // (do as much scalar math as possible rather than vector math)\n"
673 "# ifdef USESPECULAR\n"
674 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
675 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
676 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
678 " // calculate directional shading\n"
679 " 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"
681 "# ifdef USEDIFFUSE\n"
682 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
683 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
685 " // calculate directional shading\n"
686 " 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"
688 " // calculate directionless shading\n"
689 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
693 "# ifdef USECUBEFILTER\n"
694 " // apply light cubemap filter\n"
695 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
696 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
698 " color *= myhvec4(gl_Color);\n"
699 "#endif // MODE_LIGHTSOURCE\n"
704 "#ifdef MODE_LIGHTDIRECTION\n"
705 " // directional model lighting\n"
707 " // get the surface normal and light normal\n"
708 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
709 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
711 " // calculate directional shading\n"
712 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
713 "# ifdef USESPECULAR\n"
714 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
715 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
717 " color *= myhvec4(gl_Color);\n"
718 "#endif // MODE_LIGHTDIRECTION\n"
723 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
724 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
726 " // get the surface normal and light normal\n"
727 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
729 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
730 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
731 " // calculate directional shading\n"
732 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
733 "# ifdef USESPECULAR\n"
734 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
735 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
738 " // apply lightmap color\n"
739 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
740 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
745 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
746 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
748 " // get the surface normal and light normal\n"
749 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
751 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
752 " // calculate directional shading\n"
753 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
754 "# ifdef USESPECULAR\n"
755 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
756 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
759 " // apply lightmap color\n"
760 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
761 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
766 "#ifdef MODE_LIGHTMAP\n"
767 " // apply lightmap color\n"
768 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
769 "#endif // MODE_LIGHTMAP\n"
778 "#ifdef MODE_LIGHTSOURCE\n"
780 " color.rgb *= color.a;\n"
784 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
785 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
786 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
787 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0));\n"
788 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
790 "# ifdef USEREFLECTION\n"
791 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
792 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
793 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
794 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw));\n"
800 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
805 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
808 "#ifdef USECONTRASTBOOST\n"
809 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
811 " color.rgb *= SceneBrightness;\n"
814 " gl_FragColor = vec4(color);\n"
817 "#endif // FRAGMENT_SHADER\n"
820 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
821 const char *permutationinfo[][2] =
823 {"#define MODE_LIGHTMAP\n", " lightmap"},
824 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
825 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
826 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
827 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
828 {"#define USEWATER\n", " water"},
829 {"#define USEREFLECTION\n", " reflection"},
830 {"#define USEGLOW\n", " glow"},
831 {"#define USEFOG\n", " fog"},
832 {"#define USECOLORMAPPING\n", " colormapping"},
833 {"#define USEDIFFUSE\n", " diffuse"},
834 {"#define USECONTRASTBOOST\n", " contrastboost"},
835 {"#define USESPECULAR\n", " specular"},
836 {"#define USECUBEFILTER\n", " cubefilter"},
837 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
838 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
842 void R_GLSL_CompilePermutation(const char *filename, int permutation)
845 qboolean shaderfound;
846 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
847 int vertstrings_count;
848 int geomstrings_count;
849 int fragstrings_count;
851 const char *vertstrings_list[32+1];
852 const char *geomstrings_list[32+1];
853 const char *fragstrings_list[32+1];
854 char permutationname[256];
859 vertstrings_list[0] = "#define VERTEX_SHADER\n";
860 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
861 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
862 vertstrings_count = 1;
863 geomstrings_count = 1;
864 fragstrings_count = 1;
865 permutationname[0] = 0;
866 for (i = 0;permutationinfo[i][0];i++)
868 if (permutation & (1<<i))
870 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
871 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
872 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
873 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
877 // keep line numbers correct
878 vertstrings_list[vertstrings_count++] = "\n";
879 geomstrings_list[geomstrings_count++] = "\n";
880 fragstrings_list[fragstrings_count++] = "\n";
883 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
887 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
888 vertstrings_list[vertstrings_count++] = shaderstring;
889 geomstrings_list[geomstrings_count++] = shaderstring;
890 fragstrings_list[fragstrings_count++] = shaderstring;
893 else if (!strcmp(filename, "glsl/default.glsl"))
895 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
896 vertstrings_list[vertstrings_count++] = builtinshaderstring;
897 geomstrings_list[geomstrings_count++] = builtinshaderstring;
898 fragstrings_list[fragstrings_count++] = builtinshaderstring;
901 // clear any lists that are not needed by this shader
902 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
903 vertstrings_count = 0;
904 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
905 geomstrings_count = 0;
906 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
907 fragstrings_count = 0;
908 // compile the shader program
909 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
910 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
914 qglUseProgramObjectARB(p->program);CHECKGLERROR
915 // look up all the uniform variable names we care about, so we don't
916 // have to look them up every time we set them
917 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
918 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
919 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
920 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
921 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
922 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
923 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
924 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
925 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
926 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
927 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
928 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
929 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
930 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
931 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
932 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
933 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
934 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
935 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
936 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
937 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
938 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
939 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
940 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
941 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
942 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
943 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
944 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
945 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
946 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
947 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
948 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
949 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
950 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
951 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
952 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
953 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
954 // initialize the samplers to refer to the texture units we use
955 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
956 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
957 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
958 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
959 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
960 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
961 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
962 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
963 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
964 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
965 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
966 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
967 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
969 qglUseProgramObjectARB(0);CHECKGLERROR
972 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
974 Mem_Free(shaderstring);
977 void R_GLSL_Restart_f(void)
980 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
981 if (r_glsl_permutations[i].program)
982 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
983 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
986 void R_GLSL_DumpShader_f(void)
990 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
993 Con_Printf("failed to write to glsl/default.glsl\n");
997 FS_Print(file, "// The engine may define the following macros:\n");
998 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
999 for (i = 0;permutationinfo[i][0];i++)
1000 FS_Printf(file, "// %s", permutationinfo[i][0]);
1001 FS_Print(file, "\n");
1002 FS_Print(file, builtinshaderstring);
1005 Con_Printf("glsl/default.glsl written\n");
1008 extern rtexture_t *r_shadow_attenuationgradienttexture;
1009 extern rtexture_t *r_shadow_attenuation2dtexture;
1010 extern rtexture_t *r_shadow_attenuation3dtexture;
1011 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1013 // select a permutation of the lighting shader appropriate to this
1014 // combination of texture, entity, light source, and fogging, only use the
1015 // minimum features necessary to avoid wasting rendering time in the
1016 // fragment shader on features that are not being used
1017 const char *shaderfilename = NULL;
1018 unsigned int permutation = 0;
1020 r_glsl_permutation = NULL;
1021 // TODO: implement geometry-shader based shadow volumes someday
1022 if (rsurface.rtlight)
1025 shaderfilename = "glsl/default.glsl";
1026 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1027 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1028 permutation |= SHADERPERMUTATION_CUBEFILTER;
1029 if (diffusescale > 0)
1030 permutation |= SHADERPERMUTATION_DIFFUSE;
1031 if (specularscale > 0)
1032 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1033 if (r_refdef.fogenabled)
1034 permutation |= SHADERPERMUTATION_FOG;
1035 if (rsurface.texture->colormapping)
1036 permutation |= SHADERPERMUTATION_COLORMAPPING;
1037 if (r_glsl_offsetmapping.integer)
1039 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1040 if (r_glsl_offsetmapping_reliefmapping.integer)
1041 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1043 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1044 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1046 permutation |= SHADERPERMUTATION_WATER;
1047 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1048 permutation |= SHADERPERMUTATION_REFLECTION;
1050 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1052 // bright unshaded geometry
1053 shaderfilename = "glsl/default.glsl";
1054 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1055 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1056 if (rsurface.texture->currentskinframe->glow)
1057 permutation |= SHADERPERMUTATION_GLOW;
1058 if (r_refdef.fogenabled)
1059 permutation |= SHADERPERMUTATION_FOG;
1060 if (rsurface.texture->colormapping)
1061 permutation |= SHADERPERMUTATION_COLORMAPPING;
1062 if (r_glsl_offsetmapping.integer)
1064 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1065 if (r_glsl_offsetmapping_reliefmapping.integer)
1066 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1068 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1069 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1070 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1071 permutation |= SHADERPERMUTATION_WATER;
1072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1073 permutation |= SHADERPERMUTATION_REFLECTION;
1075 else if (modellighting)
1077 // directional model lighting
1078 shaderfilename = "glsl/default.glsl";
1079 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1080 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1081 if (rsurface.texture->currentskinframe->glow)
1082 permutation |= SHADERPERMUTATION_GLOW;
1083 if (specularscale > 0)
1084 permutation |= SHADERPERMUTATION_SPECULAR;
1085 if (r_refdef.fogenabled)
1086 permutation |= SHADERPERMUTATION_FOG;
1087 if (rsurface.texture->colormapping)
1088 permutation |= SHADERPERMUTATION_COLORMAPPING;
1089 if (r_glsl_offsetmapping.integer)
1091 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1092 if (r_glsl_offsetmapping_reliefmapping.integer)
1093 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1095 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1096 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1098 permutation |= SHADERPERMUTATION_WATER;
1099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1100 permutation |= SHADERPERMUTATION_REFLECTION;
1105 shaderfilename = "glsl/default.glsl";
1106 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1107 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1109 // deluxemapping (light direction texture)
1110 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1111 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1113 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1114 if (specularscale > 0)
1115 permutation |= SHADERPERMUTATION_SPECULAR;
1117 else if (r_glsl_deluxemapping.integer >= 2)
1119 // fake deluxemapping (uniform light direction in tangentspace)
1120 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1121 if (specularscale > 0)
1122 permutation |= SHADERPERMUTATION_SPECULAR;
1126 // ordinary lightmapping
1127 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1129 if (rsurface.texture->currentskinframe->glow)
1130 permutation |= SHADERPERMUTATION_GLOW;
1131 if (r_refdef.fogenabled)
1132 permutation |= SHADERPERMUTATION_FOG;
1133 if (rsurface.texture->colormapping)
1134 permutation |= SHADERPERMUTATION_COLORMAPPING;
1135 if (r_glsl_offsetmapping.integer)
1137 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1138 if (r_glsl_offsetmapping_reliefmapping.integer)
1139 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1141 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1142 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1144 permutation |= SHADERPERMUTATION_WATER;
1145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1146 permutation |= SHADERPERMUTATION_REFLECTION;
1148 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1150 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1151 R_GLSL_CompilePermutation(shaderfilename, permutation);
1152 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1154 // remove features until we find a valid permutation
1156 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1160 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");
1161 Cvar_SetValueQuick(&r_glsl, 0);
1162 return 0; // no bit left to clear
1164 // reduce i more quickly whenever it would not remove any bits
1165 if (!(permutation & i))
1168 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1169 R_GLSL_CompilePermutation(shaderfilename, permutation);
1170 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1175 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1177 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1178 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1179 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1181 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1182 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1183 if (permutation & SHADERPERMUTATION_DIFFUSE)
1185 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1186 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1187 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1188 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1192 // ambient only is simpler
1193 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1194 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1195 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1196 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1199 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1201 if (r_glsl_permutation->loc_AmbientColor >= 0)
1202 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1203 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1204 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1205 if (r_glsl_permutation->loc_SpecularColor >= 0)
1206 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1207 if (r_glsl_permutation->loc_LightDir >= 0)
1208 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1212 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1213 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1214 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1216 nmap = rsurface.texture->currentskinframe->nmap;
1217 if (gl_lightmaps.integer)
1218 nmap = r_texture_blanknormalmap;
1219 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1220 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1221 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1222 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1223 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1224 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1225 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1226 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1227 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1228 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1229 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1230 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1231 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1232 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1233 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1235 // The formula used is actually:
1236 // color.rgb *= SceneBrightness;
1237 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1238 // I simplify that to
1239 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1240 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1242 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1243 // and do [[calculations]] here in the engine
1244 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1245 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1248 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1249 if (r_glsl_permutation->loc_FogColor >= 0)
1251 // additive passes are only darkened by fog, not tinted
1252 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1253 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1255 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1257 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1258 if (r_glsl_permutation->loc_Color_Pants >= 0)
1260 if (rsurface.texture->currentskinframe->pants)
1261 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1263 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1265 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1267 if (rsurface.texture->currentskinframe->shirt)
1268 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1270 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1272 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1273 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1274 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1275 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);
1276 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]);
1277 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]);
1278 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);
1279 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);
1284 void R_SwitchSurfaceShader(int permutation)
1286 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1288 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1290 qglUseProgramObjectARB(r_glsl_permutation->program);
1295 #define SKINFRAME_HASH 1024
1299 int loadsequence; // incremented each level change
1300 memexpandablearray_t array;
1301 skinframe_t *hash[SKINFRAME_HASH];
1305 void R_SkinFrame_PrepareForPurge(void)
1307 r_skinframe.loadsequence++;
1308 // wrap it without hitting zero
1309 if (r_skinframe.loadsequence >= 200)
1310 r_skinframe.loadsequence = 1;
1313 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1317 // mark the skinframe as used for the purging code
1318 skinframe->loadsequence = r_skinframe.loadsequence;
1321 void R_SkinFrame_Purge(void)
1325 for (i = 0;i < SKINFRAME_HASH;i++)
1327 for (s = r_skinframe.hash[i];s;s = s->next)
1329 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1331 if (s->base == r_texture_notexture) s->base = NULL;
1332 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1333 if (s->merged == s->base) s->merged = NULL;
1334 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1335 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1336 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1337 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1338 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1339 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1340 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1341 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1342 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1343 s->loadsequence = 0;
1349 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1353 char basename[MAX_QPATH];
1355 Image_StripImageExtension(name, basename, sizeof(basename));
1357 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1358 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1359 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1365 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1366 memset(item, 0, sizeof(*item));
1367 strlcpy(item->basename, basename, sizeof(item->basename));
1368 item->textureflags = textureflags;
1369 item->comparewidth = comparewidth;
1370 item->compareheight = compareheight;
1371 item->comparecrc = comparecrc;
1372 item->next = r_skinframe.hash[hashindex];
1373 r_skinframe.hash[hashindex] = item;
1375 R_SkinFrame_MarkUsed(item);
1379 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1381 // FIXME: it should be possible to disable loading various layers using
1382 // cvars, to prevent wasted loading time and memory usage if the user does
1384 qboolean loadnormalmap = true;
1385 qboolean loadgloss = true;
1386 qboolean loadpantsandshirt = true;
1387 qboolean loadglow = true;
1389 unsigned char *pixels;
1390 unsigned char *bumppixels;
1391 unsigned char *basepixels = NULL;
1392 int basepixels_width;
1393 int basepixels_height;
1394 skinframe_t *skinframe;
1396 if (cls.state == ca_dedicated)
1399 // return an existing skinframe if already loaded
1400 // if loading of the first image fails, don't make a new skinframe as it
1401 // would cause all future lookups of this to be missing
1402 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1403 if (skinframe && skinframe->base)
1406 basepixels = loadimagepixels(name, complain, 0, 0);
1407 if (basepixels == NULL)
1410 // we've got some pixels to store, so really allocate this new texture now
1412 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1413 skinframe->stain = NULL;
1414 skinframe->merged = NULL;
1415 skinframe->base = r_texture_notexture;
1416 skinframe->pants = NULL;
1417 skinframe->shirt = NULL;
1418 skinframe->nmap = r_texture_blanknormalmap;
1419 skinframe->gloss = NULL;
1420 skinframe->glow = NULL;
1421 skinframe->fog = NULL;
1423 basepixels_width = image_width;
1424 basepixels_height = image_height;
1425 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);
1427 if (textureflags & TEXF_ALPHA)
1429 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1430 if (basepixels[j] < 255)
1432 if (j < basepixels_width * basepixels_height * 4)
1434 // has transparent pixels
1435 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1436 for (j = 0;j < image_width * image_height * 4;j += 4)
1441 pixels[j+3] = basepixels[j+3];
1443 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);
1448 // _norm is the name used by tenebrae and has been adopted as standard
1451 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1453 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);
1457 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1459 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1460 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1461 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);
1463 Mem_Free(bumppixels);
1465 else if (r_shadow_bumpscale_basetexture.value > 0)
1467 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1468 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1469 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);
1473 // _luma is supported for tenebrae compatibility
1474 // (I think it's a very stupid name, but oh well)
1475 // _glow is the preferred name
1476 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;}
1477 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;}
1478 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;}
1479 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;}
1482 Mem_Free(basepixels);
1487 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)
1492 for (i = 0;i < width*height;i++)
1493 if (((unsigned char *)&palette[in[i]])[3] > 0)
1495 if (i == width*height)
1498 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1501 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)
1504 unsigned char *temp1, *temp2;
1505 skinframe_t *skinframe;
1507 if (cls.state == ca_dedicated)
1510 // if already loaded just return it, otherwise make a new skinframe
1511 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1512 if (skinframe && skinframe->base)
1515 skinframe->stain = NULL;
1516 skinframe->merged = NULL;
1517 skinframe->base = r_texture_notexture;
1518 skinframe->pants = NULL;
1519 skinframe->shirt = NULL;
1520 skinframe->nmap = r_texture_blanknormalmap;
1521 skinframe->gloss = NULL;
1522 skinframe->glow = NULL;
1523 skinframe->fog = NULL;
1525 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1529 if (bitsperpixel == 32)
1531 if (r_shadow_bumpscale_basetexture.value > 0)
1533 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1534 temp2 = temp1 + width * height * 4;
1535 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1536 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1539 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1540 if (textureflags & TEXF_ALPHA)
1542 for (i = 3;i < width * height * 4;i += 4)
1543 if (skindata[i] < 255)
1545 if (i < width * height * 4)
1547 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1548 memcpy(fogpixels, skindata, width * height * 4);
1549 for (i = 0;i < width * height * 4;i += 4)
1550 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1551 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1552 Mem_Free(fogpixels);
1556 else if (bitsperpixel == 8)
1558 if (r_shadow_bumpscale_basetexture.value > 0)
1560 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1561 temp2 = temp1 + width * height * 4;
1562 if (bitsperpixel == 32)
1563 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1566 // use either a custom palette or the quake palette
1567 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1568 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1570 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1573 // use either a custom palette, or the quake palette
1574 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
1575 if (!palette && loadglowtexture)
1576 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1577 if (!palette && loadpantsandshirt)
1579 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1580 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1582 if (skinframe->pants || skinframe->shirt)
1583 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1584 if (textureflags & TEXF_ALPHA)
1586 // if not using a custom alphapalette, use the quake one
1588 alphapalette = palette_alpha;
1589 for (i = 0;i < width * height;i++)
1590 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1592 if (i < width * height)
1593 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1600 skinframe_t *R_SkinFrame_LoadMissing(void)
1602 skinframe_t *skinframe;
1604 if (cls.state == ca_dedicated)
1607 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1608 skinframe->stain = NULL;
1609 skinframe->merged = NULL;
1610 skinframe->base = r_texture_notexture;
1611 skinframe->pants = NULL;
1612 skinframe->shirt = NULL;
1613 skinframe->nmap = r_texture_blanknormalmap;
1614 skinframe->gloss = NULL;
1615 skinframe->glow = NULL;
1616 skinframe->fog = NULL;
1621 void gl_main_start(void)
1626 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1627 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1629 alpha = 1 - exp(r / ((double)x*(double)x));
1630 if (x == FOGMASKTABLEWIDTH - 1)
1632 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1635 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1636 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1638 // set up r_skinframe loading system for textures
1639 memset(&r_skinframe, 0, sizeof(r_skinframe));
1640 r_skinframe.loadsequence = 1;
1641 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1643 r_main_texturepool = R_AllocTexturePool();
1644 R_BuildBlankTextures();
1646 if (gl_texturecubemap)
1649 R_BuildNormalizationCube();
1651 R_BuildFogTexture();
1652 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1653 memset(&r_waterstate, 0, sizeof(r_waterstate));
1654 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1655 memset(&r_svbsp, 0, sizeof (r_svbsp));
1658 void gl_main_shutdown(void)
1660 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1661 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1663 // clear out the r_skinframe state
1664 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1665 memset(&r_skinframe, 0, sizeof(r_skinframe));
1668 Mem_Free(r_svbsp.nodes);
1669 memset(&r_svbsp, 0, sizeof (r_svbsp));
1670 R_FreeTexturePool(&r_main_texturepool);
1671 r_texture_blanknormalmap = NULL;
1672 r_texture_white = NULL;
1673 r_texture_grey128 = NULL;
1674 r_texture_black = NULL;
1675 r_texture_whitecube = NULL;
1676 r_texture_normalizationcube = NULL;
1677 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1678 memset(&r_waterstate, 0, sizeof(r_waterstate));
1682 extern void CL_ParseEntityLump(char *entitystring);
1683 void gl_main_newmap(void)
1685 // FIXME: move this code to client
1687 char *entities, entname[MAX_QPATH];
1690 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1691 l = (int)strlen(entname) - 4;
1692 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1694 memcpy(entname + l, ".ent", 5);
1695 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1697 CL_ParseEntityLump(entities);
1702 if (cl.worldmodel->brush.entities)
1703 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1707 void GL_Main_Init(void)
1709 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1711 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1712 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1713 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1714 if (gamemode == GAME_NEHAHRA)
1716 Cvar_RegisterVariable (&gl_fogenable);
1717 Cvar_RegisterVariable (&gl_fogdensity);
1718 Cvar_RegisterVariable (&gl_fogred);
1719 Cvar_RegisterVariable (&gl_foggreen);
1720 Cvar_RegisterVariable (&gl_fogblue);
1721 Cvar_RegisterVariable (&gl_fogstart);
1722 Cvar_RegisterVariable (&gl_fogend);
1724 Cvar_RegisterVariable(&r_depthfirst);
1725 Cvar_RegisterVariable(&r_nearclip);
1726 Cvar_RegisterVariable(&r_showbboxes);
1727 Cvar_RegisterVariable(&r_showsurfaces);
1728 Cvar_RegisterVariable(&r_showtris);
1729 Cvar_RegisterVariable(&r_shownormals);
1730 Cvar_RegisterVariable(&r_showlighting);
1731 Cvar_RegisterVariable(&r_showshadowvolumes);
1732 Cvar_RegisterVariable(&r_showcollisionbrushes);
1733 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1734 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1735 Cvar_RegisterVariable(&r_showdisabledepthtest);
1736 Cvar_RegisterVariable(&r_drawportals);
1737 Cvar_RegisterVariable(&r_drawentities);
1738 Cvar_RegisterVariable(&r_cullentities_trace);
1739 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1740 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1741 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1742 Cvar_RegisterVariable(&r_drawviewmodel);
1743 Cvar_RegisterVariable(&r_speeds);
1744 Cvar_RegisterVariable(&r_fullbrights);
1745 Cvar_RegisterVariable(&r_wateralpha);
1746 Cvar_RegisterVariable(&r_dynamic);
1747 Cvar_RegisterVariable(&r_fullbright);
1748 Cvar_RegisterVariable(&r_shadows);
1749 Cvar_RegisterVariable(&r_shadows_throwdistance);
1750 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1751 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1752 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1753 Cvar_RegisterVariable(&r_textureunits);
1754 Cvar_RegisterVariable(&r_glsl);
1755 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1756 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1757 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1758 Cvar_RegisterVariable(&r_glsl_water);
1759 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1760 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1761 Cvar_RegisterVariable(&r_glsl_water_refractcolor_r);
1762 Cvar_RegisterVariable(&r_glsl_water_refractcolor_g);
1763 Cvar_RegisterVariable(&r_glsl_water_refractcolor_b);
1764 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_r);
1765 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_g);
1766 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_b);
1767 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1768 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1769 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1770 Cvar_RegisterVariable(&r_lerpsprites);
1771 Cvar_RegisterVariable(&r_lerpmodels);
1772 Cvar_RegisterVariable(&r_waterscroll);
1773 Cvar_RegisterVariable(&r_bloom);
1774 Cvar_RegisterVariable(&r_bloom_colorscale);
1775 Cvar_RegisterVariable(&r_bloom_brighten);
1776 Cvar_RegisterVariable(&r_bloom_blur);
1777 Cvar_RegisterVariable(&r_bloom_resolution);
1778 Cvar_RegisterVariable(&r_bloom_colorexponent);
1779 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1780 Cvar_RegisterVariable(&r_hdr);
1781 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1782 Cvar_RegisterVariable(&r_glsl_contrastboost);
1783 Cvar_RegisterVariable(&r_hdr_glowintensity);
1784 Cvar_RegisterVariable(&r_hdr_range);
1785 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1786 Cvar_RegisterVariable(&developer_texturelogging);
1787 Cvar_RegisterVariable(&gl_lightmaps);
1788 Cvar_RegisterVariable(&r_test);
1789 Cvar_RegisterVariable(&r_batchmode);
1790 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1791 Cvar_SetValue("r_fullbrights", 0);
1792 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1795 extern void R_Textures_Init(void);
1796 extern void GL_Draw_Init(void);
1797 extern void GL_Main_Init(void);
1798 extern void R_Shadow_Init(void);
1799 extern void R_Sky_Init(void);
1800 extern void GL_Surf_Init(void);
1801 extern void R_Light_Init(void);
1802 extern void R_Particles_Init(void);
1803 extern void R_Explosion_Init(void);
1804 extern void gl_backend_init(void);
1805 extern void Sbar_Init(void);
1806 extern void R_LightningBeams_Init(void);
1807 extern void Mod_RenderInit(void);
1809 void Render_Init(void)
1822 R_LightningBeams_Init();
1831 extern char *ENGINE_EXTENSIONS;
1834 VID_CheckExtensions();
1836 // LordHavoc: report supported extensions
1837 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1839 // clear to black (loading plaque will be seen over this)
1841 qglClearColor(0,0,0,1);CHECKGLERROR
1842 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1845 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1849 for (i = 0;i < r_view.numfrustumplanes;i++)
1851 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1854 p = r_view.frustum + i;
1859 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1863 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1867 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1871 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1875 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1879 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1883 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1887 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1895 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1899 for (i = 0;i < numplanes;i++)
1906 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1910 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1914 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1918 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1922 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1926 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1930 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1934 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1942 //==================================================================================
1944 static void R_UpdateEntityLighting(entity_render_t *ent)
1946 vec3_t tempdiffusenormal;
1948 // fetch the lighting from the worldmodel data
1949 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));
1950 VectorClear(ent->modellight_diffuse);
1951 VectorClear(tempdiffusenormal);
1952 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1955 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1956 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1959 VectorSet(ent->modellight_ambient, 1, 1, 1);
1961 // move the light direction into modelspace coordinates for lighting code
1962 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1963 if(VectorLength2(ent->modellight_lightdir) > 0)
1965 VectorNormalize(ent->modellight_lightdir);
1969 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1972 // scale ambient and directional light contributions according to rendering variables
1973 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1974 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1975 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1976 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1977 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1978 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1981 static void R_View_UpdateEntityVisible (void)
1984 entity_render_t *ent;
1986 if (!r_drawentities.integer)
1989 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1990 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1992 // worldmodel can check visibility
1993 for (i = 0;i < r_refdef.numentities;i++)
1995 ent = r_refdef.entities[i];
1996 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));
1998 if(r_cullentities_trace.integer)
2000 for (i = 0;i < r_refdef.numentities;i++)
2002 ent = r_refdef.entities[i];
2003 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2005 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2006 ent->last_trace_visibility = realtime;
2007 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2008 r_viewcache.entityvisible[i] = 0;
2015 // no worldmodel or it can't check visibility
2016 for (i = 0;i < r_refdef.numentities;i++)
2018 ent = r_refdef.entities[i];
2019 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2023 // update entity lighting (even on hidden entities for r_shadows)
2024 for (i = 0;i < r_refdef.numentities;i++)
2025 R_UpdateEntityLighting(r_refdef.entities[i]);
2028 // only used if skyrendermasked, and normally returns false
2029 int R_DrawBrushModelsSky (void)
2032 entity_render_t *ent;
2034 if (!r_drawentities.integer)
2038 for (i = 0;i < r_refdef.numentities;i++)
2040 if (!r_viewcache.entityvisible[i])
2042 ent = r_refdef.entities[i];
2043 if (!ent->model || !ent->model->DrawSky)
2045 ent->model->DrawSky(ent);
2051 static void R_DrawNoModel(entity_render_t *ent);
2052 static void R_DrawModels(void)
2055 entity_render_t *ent;
2057 if (!r_drawentities.integer)
2060 for (i = 0;i < r_refdef.numentities;i++)
2062 if (!r_viewcache.entityvisible[i])
2064 ent = r_refdef.entities[i];
2065 r_refdef.stats.entities++;
2066 if (ent->model && ent->model->Draw != NULL)
2067 ent->model->Draw(ent);
2073 static void R_DrawModelsDepth(void)
2076 entity_render_t *ent;
2078 if (!r_drawentities.integer)
2081 for (i = 0;i < r_refdef.numentities;i++)
2083 if (!r_viewcache.entityvisible[i])
2085 ent = r_refdef.entities[i];
2086 r_refdef.stats.entities++;
2087 if (ent->model && ent->model->DrawDepth != NULL)
2088 ent->model->DrawDepth(ent);
2092 static void R_DrawModelsDebug(void)
2095 entity_render_t *ent;
2097 if (!r_drawentities.integer)
2100 for (i = 0;i < r_refdef.numentities;i++)
2102 if (!r_viewcache.entityvisible[i])
2104 ent = r_refdef.entities[i];
2105 r_refdef.stats.entities++;
2106 if (ent->model && ent->model->DrawDebug != NULL)
2107 ent->model->DrawDebug(ent);
2111 static void R_DrawModelsAddWaterPlanes(void)
2114 entity_render_t *ent;
2116 if (!r_drawentities.integer)
2119 for (i = 0;i < r_refdef.numentities;i++)
2121 if (!r_viewcache.entityvisible[i])
2123 ent = r_refdef.entities[i];
2124 r_refdef.stats.entities++;
2125 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2126 ent->model->DrawAddWaterPlanes(ent);
2130 static void R_View_SetFrustum(void)
2133 double slopex, slopey;
2135 // break apart the view matrix into vectors for various purposes
2136 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2137 VectorNegate(r_view.left, r_view.right);
2140 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2141 r_view.frustum[0].normal[1] = 0 - 0;
2142 r_view.frustum[0].normal[2] = -1 - 0;
2143 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2144 r_view.frustum[1].normal[1] = 0 + 0;
2145 r_view.frustum[1].normal[2] = -1 + 0;
2146 r_view.frustum[2].normal[0] = 0 - 0;
2147 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2148 r_view.frustum[2].normal[2] = -1 - 0;
2149 r_view.frustum[3].normal[0] = 0 + 0;
2150 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2151 r_view.frustum[3].normal[2] = -1 + 0;
2155 zNear = r_refdef.nearclip;
2156 nudge = 1.0 - 1.0 / (1<<23);
2157 r_view.frustum[4].normal[0] = 0 - 0;
2158 r_view.frustum[4].normal[1] = 0 - 0;
2159 r_view.frustum[4].normal[2] = -1 - -nudge;
2160 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2161 r_view.frustum[5].normal[0] = 0 + 0;
2162 r_view.frustum[5].normal[1] = 0 + 0;
2163 r_view.frustum[5].normal[2] = -1 + -nudge;
2164 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2170 r_view.frustum[0].normal[0] = m[3] - m[0];
2171 r_view.frustum[0].normal[1] = m[7] - m[4];
2172 r_view.frustum[0].normal[2] = m[11] - m[8];
2173 r_view.frustum[0].dist = m[15] - m[12];
2175 r_view.frustum[1].normal[0] = m[3] + m[0];
2176 r_view.frustum[1].normal[1] = m[7] + m[4];
2177 r_view.frustum[1].normal[2] = m[11] + m[8];
2178 r_view.frustum[1].dist = m[15] + m[12];
2180 r_view.frustum[2].normal[0] = m[3] - m[1];
2181 r_view.frustum[2].normal[1] = m[7] - m[5];
2182 r_view.frustum[2].normal[2] = m[11] - m[9];
2183 r_view.frustum[2].dist = m[15] - m[13];
2185 r_view.frustum[3].normal[0] = m[3] + m[1];
2186 r_view.frustum[3].normal[1] = m[7] + m[5];
2187 r_view.frustum[3].normal[2] = m[11] + m[9];
2188 r_view.frustum[3].dist = m[15] + m[13];
2190 r_view.frustum[4].normal[0] = m[3] - m[2];
2191 r_view.frustum[4].normal[1] = m[7] - m[6];
2192 r_view.frustum[4].normal[2] = m[11] - m[10];
2193 r_view.frustum[4].dist = m[15] - m[14];
2195 r_view.frustum[5].normal[0] = m[3] + m[2];
2196 r_view.frustum[5].normal[1] = m[7] + m[6];
2197 r_view.frustum[5].normal[2] = m[11] + m[10];
2198 r_view.frustum[5].dist = m[15] + m[14];
2203 if (r_view.useperspective)
2205 slopex = 1.0 / r_view.frustum_x;
2206 slopey = 1.0 / r_view.frustum_y;
2207 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2208 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2209 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2210 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2211 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2213 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2214 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2215 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2216 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2217 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2219 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2220 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2221 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2222 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2223 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2227 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2228 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2229 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2230 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2231 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2232 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2233 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2234 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2235 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2236 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2238 r_view.numfrustumplanes = 5;
2240 if (r_view.useclipplane)
2242 r_view.numfrustumplanes = 6;
2243 r_view.frustum[5] = r_view.clipplane;
2246 for (i = 0;i < r_view.numfrustumplanes;i++)
2247 PlaneClassify(r_view.frustum + i);
2249 // LordHavoc: note to all quake engine coders, Quake had a special case
2250 // for 90 degrees which assumed a square view (wrong), so I removed it,
2251 // Quake2 has it disabled as well.
2253 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2254 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2255 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2256 //PlaneClassify(&frustum[0]);
2258 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2259 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2260 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2261 //PlaneClassify(&frustum[1]);
2263 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2264 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2265 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2266 //PlaneClassify(&frustum[2]);
2268 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2269 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2270 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2271 //PlaneClassify(&frustum[3]);
2274 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2275 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2276 //PlaneClassify(&frustum[4]);
2279 void R_View_Update(void)
2281 R_View_SetFrustum();
2282 R_View_WorldVisibility(r_view.useclipplane);
2283 R_View_UpdateEntityVisible();
2286 void R_SetupView(void)
2288 if (!r_view.useperspective)
2289 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);
2290 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2291 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2293 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2295 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2297 if (r_view.useclipplane)
2299 // LordHavoc: couldn't figure out how to make this approach the
2300 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2301 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2302 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2303 dist = r_view.clipplane.dist;
2304 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2308 void R_ResetViewRendering2D(void)
2310 if (gl_support_fragment_shader)
2312 qglUseProgramObjectARB(0);CHECKGLERROR
2317 // GL is weird because it's bottom to top, r_view.y is top to bottom
2318 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2319 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2320 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2321 GL_Color(1, 1, 1, 1);
2322 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2323 GL_BlendFunc(GL_ONE, GL_ZERO);
2324 GL_AlphaTest(false);
2325 GL_ScissorTest(false);
2326 GL_DepthMask(false);
2327 GL_DepthRange(0, 1);
2328 GL_DepthTest(false);
2329 R_Mesh_Matrix(&identitymatrix);
2330 R_Mesh_ResetTextureState();
2331 GL_PolygonOffset(0, 0);
2332 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2333 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2334 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2335 qglStencilMask(~0);CHECKGLERROR
2336 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2337 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2338 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2341 void R_ResetViewRendering3D(void)
2343 if (gl_support_fragment_shader)
2345 qglUseProgramObjectARB(0);CHECKGLERROR
2350 // GL is weird because it's bottom to top, r_view.y is top to bottom
2351 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2353 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2354 GL_Color(1, 1, 1, 1);
2355 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2356 GL_BlendFunc(GL_ONE, GL_ZERO);
2357 GL_AlphaTest(false);
2358 GL_ScissorTest(true);
2360 GL_DepthRange(0, 1);
2362 R_Mesh_Matrix(&identitymatrix);
2363 R_Mesh_ResetTextureState();
2364 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2365 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2366 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2367 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2368 qglStencilMask(~0);CHECKGLERROR
2369 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2370 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2371 GL_CullFace(r_view.cullface_back);
2375 R_Bloom_SetupShader(
2377 "// written by Forest 'LordHavoc' Hale\n"
2379 "// common definitions between vertex shader and fragment shader:\n"
2381 "#ifdef __GLSL_CG_DATA_TYPES\n"
2382 "#define myhalf half\n"
2383 "#define myhvec2 hvec2\n"
2384 "#define myhvec3 hvec3\n"
2385 "#define myhvec4 hvec4\n"
2387 "#define myhalf float\n"
2388 "#define myhvec2 vec2\n"
2389 "#define myhvec3 vec3\n"
2390 "#define myhvec4 vec4\n"
2393 "varying vec2 ScreenTexCoord;\n"
2394 "varying vec2 BloomTexCoord;\n"
2399 "// vertex shader specific:\n"
2400 "#ifdef VERTEX_SHADER\n"
2404 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2405 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2406 " // transform vertex to camera space, using ftransform to match non-VS\n"
2408 " gl_Position = ftransform();\n"
2411 "#endif // VERTEX_SHADER\n"
2416 "// fragment shader specific:\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2422 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2423 " for (x = -BLUR_X;x <= BLUR_X;x++)
2424 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2425 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2426 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2427 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2429 " gl_FragColor = vec4(color);\n"
2432 "#endif // FRAGMENT_SHADER\n"
2435 void R_RenderScene(qboolean addwaterplanes);
2437 static void R_Water_StartFrame(void)
2440 int waterwidth, waterheight, texturewidth, textureheight;
2441 r_waterstate_waterplane_t *p;
2443 // set waterwidth and waterheight to the water resolution that will be
2444 // used (often less than the screen resolution for faster rendering)
2445 waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2446 waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2448 // calculate desired texture sizes
2449 // can't use water if the card does not support the texture size
2450 if (!r_glsl_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2451 texturewidth = textureheight = waterwidth = waterheight = 0;
2452 else if (gl_support_arb_texture_non_power_of_two)
2454 texturewidth = waterwidth;
2455 textureheight = waterheight;
2459 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2460 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2463 // allocate textures as needed
2464 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2466 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2467 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2469 if (p->texture_refraction)
2470 R_FreeTexture(p->texture_refraction);
2471 p->texture_refraction = NULL;
2472 if (p->texture_reflection)
2473 R_FreeTexture(p->texture_reflection);
2474 p->texture_reflection = NULL;
2476 memset(&r_waterstate, 0, sizeof(r_waterstate));
2477 r_waterstate.waterwidth = waterwidth;
2478 r_waterstate.waterheight = waterheight;
2479 r_waterstate.texturewidth = texturewidth;
2480 r_waterstate.textureheight = textureheight;
2483 if (r_waterstate.waterwidth)
2485 r_waterstate.enabled = true;
2487 // set up variables that will be used in shader setup
2488 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2489 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2490 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2491 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2494 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2495 r_waterstate.numwaterplanes = 0;
2498 static void R_Water_AddWaterPlane(msurface_t *surface)
2500 int triangleindex, planeindex;
2506 r_waterstate_waterplane_t *p;
2507 // just use the first triangle with a valid normal for any decisions
2508 VectorClear(normal);
2509 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2511 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2512 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2513 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2514 TriangleNormal(vert[0], vert[1], vert[2], normal);
2515 if (VectorLength2(normal) >= 0.001)
2518 // now find the center of this surface
2519 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2521 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2522 VectorAdd(center, vert[0], center);
2524 f = 1.0 / surface->num_triangles*3;
2525 VectorScale(center, f, center);
2527 // find a matching plane if there is one
2528 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2529 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2531 if (planeindex >= r_waterstate.maxwaterplanes)
2532 return; // nothing we can do, out of planes
2534 // if this triangle does not fit any known plane rendered this frame, add one
2535 if (planeindex >= r_waterstate.numwaterplanes)
2537 // store the new plane
2538 r_waterstate.numwaterplanes++;
2539 VectorCopy(normal, p->plane.normal);
2540 VectorNormalize(p->plane.normal);
2541 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2542 PlaneClassify(&p->plane);
2543 // flip the plane if it does not face the viewer
2544 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2546 VectorNegate(p->plane.normal, p->plane.normal);
2547 p->plane.dist *= -1;
2548 PlaneClassify(&p->plane);
2550 // clear materialflags and pvs
2551 p->materialflags = 0;
2552 p->pvsvalid = false;
2554 // merge this surface's materialflags into the waterplane
2555 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2556 // merge this surface's PVS into the waterplane
2557 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2559 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2564 static void R_Water_ProcessPlanes(void)
2566 r_view_t originalview;
2568 r_waterstate_waterplane_t *p;
2570 // make sure enough textures are allocated
2571 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2573 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2575 if (!p->texture_refraction)
2576 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);
2577 if (!p->texture_refraction)
2581 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2583 if (!p->texture_reflection)
2584 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);
2585 if (!p->texture_reflection)
2591 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2593 originalview = r_view;
2594 r_view.showdebug = false;
2595 r_view.width = r_waterstate.waterwidth;
2596 r_view.height = r_waterstate.waterheight;
2597 r_view.useclipplane = true;
2598 r_waterstate.renderingscene = true;
2600 // render the normal view scene and copy into texture
2601 // (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)
2602 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2604 r_view.clipplane = p->plane;
2605 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2606 r_view.clipplane.dist = -r_view.clipplane.dist;
2607 PlaneClassify(&r_view.clipplane);
2609 R_RenderScene(false);
2611 // copy view into the screen texture
2612 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2613 GL_ActiveTexture(0);
2615 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
2618 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2620 // render reflected scene and copy into texture
2621 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2622 r_view.clipplane = p->plane;
2623 // reverse the cullface settings for this render
2624 r_view.cullface_front = GL_FRONT;
2625 r_view.cullface_back = GL_BACK;
2626 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2628 r_view.usecustompvs = true;
2630 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2632 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2635 R_ResetViewRendering3D();
2638 R_RenderScene(false);
2640 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2641 GL_ActiveTexture(0);
2643 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
2645 R_ResetViewRendering3D();
2649 r_view = originalview;
2650 r_waterstate.renderingscene = false;
2654 r_view = originalview;
2655 r_waterstate.renderingscene = false;
2656 Cvar_SetValueQuick(&r_glsl_water, 0);
2657 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_glsl_water.\n");
2661 void R_Bloom_StartFrame(void)
2663 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2665 // set bloomwidth and bloomheight to the bloom resolution that will be
2666 // used (often less than the screen resolution for faster rendering)
2667 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2668 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2669 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2671 // calculate desired texture sizes
2672 if (gl_support_arb_texture_non_power_of_two)
2674 screentexturewidth = r_view.width;
2675 screentextureheight = r_view.height;
2676 bloomtexturewidth = r_bloomstate.bloomwidth;
2677 bloomtextureheight = r_bloomstate.bloomheight;
2681 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2682 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2683 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2684 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2689 screentexturewidth = screentextureheight = 0;
2691 else if (r_bloom.integer)
2696 screentexturewidth = screentextureheight = 0;
2697 bloomtexturewidth = bloomtextureheight = 0;
2700 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)
2702 // can't use bloom if the parameters are too weird
2703 // can't use bloom if the card does not support the texture size
2704 if (r_bloomstate.texture_screen)
2705 R_FreeTexture(r_bloomstate.texture_screen);
2706 if (r_bloomstate.texture_bloom)
2707 R_FreeTexture(r_bloomstate.texture_bloom);
2708 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2712 r_bloomstate.enabled = true;
2713 r_bloomstate.hdr = r_hdr.integer != 0;
2715 // allocate textures as needed
2716 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2718 if (r_bloomstate.texture_screen)
2719 R_FreeTexture(r_bloomstate.texture_screen);
2720 r_bloomstate.texture_screen = NULL;
2721 r_bloomstate.screentexturewidth = screentexturewidth;
2722 r_bloomstate.screentextureheight = screentextureheight;
2723 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2724 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);
2726 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2728 if (r_bloomstate.texture_bloom)
2729 R_FreeTexture(r_bloomstate.texture_bloom);
2730 r_bloomstate.texture_bloom = NULL;
2731 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2732 r_bloomstate.bloomtextureheight = bloomtextureheight;
2733 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2734 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);
2737 // set up a texcoord array for the full resolution screen image
2738 // (we have to keep this around to copy back during final render)
2739 r_bloomstate.screentexcoord2f[0] = 0;
2740 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2741 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2742 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2743 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2744 r_bloomstate.screentexcoord2f[5] = 0;
2745 r_bloomstate.screentexcoord2f[6] = 0;
2746 r_bloomstate.screentexcoord2f[7] = 0;
2748 // set up a texcoord array for the reduced resolution bloom image
2749 // (which will be additive blended over the screen image)
2750 r_bloomstate.bloomtexcoord2f[0] = 0;
2751 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2752 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2753 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2754 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2755 r_bloomstate.bloomtexcoord2f[5] = 0;
2756 r_bloomstate.bloomtexcoord2f[6] = 0;
2757 r_bloomstate.bloomtexcoord2f[7] = 0;
2760 void R_Bloom_CopyScreenTexture(float colorscale)
2762 r_refdef.stats.bloom++;
2764 R_ResetViewRendering2D();
2765 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2766 R_Mesh_ColorPointer(NULL, 0, 0);
2767 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2768 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2770 // copy view into the screen texture
2771 GL_ActiveTexture(0);
2773 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
2774 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2776 // now scale it down to the bloom texture size
2778 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2779 GL_BlendFunc(GL_ONE, GL_ZERO);
2780 GL_Color(colorscale, colorscale, colorscale, 1);
2781 // TODO: optimize with multitexture or GLSL
2782 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2783 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2785 // we now have a bloom image in the framebuffer
2786 // copy it into the bloom image texture for later processing
2787 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2788 GL_ActiveTexture(0);
2790 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
2791 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2794 void R_Bloom_CopyHDRTexture(void)
2796 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2797 GL_ActiveTexture(0);
2799 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
2800 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2803 void R_Bloom_MakeTexture(void)
2806 float xoffset, yoffset, r, brighten;
2808 r_refdef.stats.bloom++;
2810 R_ResetViewRendering2D();
2811 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2812 R_Mesh_ColorPointer(NULL, 0, 0);
2814 // we have a bloom image in the framebuffer
2816 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2818 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2821 r = bound(0, r_bloom_colorexponent.value / x, 1);
2822 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2823 GL_Color(r, r, r, 1);
2824 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2825 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2826 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2827 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2829 // copy the vertically blurred bloom view to a texture
2830 GL_ActiveTexture(0);
2832 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
2833 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2836 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2837 brighten = r_bloom_brighten.value;
2839 brighten *= r_hdr_range.value;
2840 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2841 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2843 for (dir = 0;dir < 2;dir++)
2845 // blend on at multiple vertical offsets to achieve a vertical blur
2846 // TODO: do offset blends using GLSL
2847 GL_BlendFunc(GL_ONE, GL_ZERO);
2848 for (x = -range;x <= range;x++)
2850 if (!dir){xoffset = 0;yoffset = x;}
2851 else {xoffset = x;yoffset = 0;}
2852 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2853 yoffset /= (float)r_bloomstate.bloomtextureheight;
2854 // compute a texcoord array with the specified x and y offset
2855 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2856 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2857 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2858 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2859 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2860 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2861 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2862 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2863 // this r value looks like a 'dot' particle, fading sharply to
2864 // black at the edges
2865 // (probably not realistic but looks good enough)
2866 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2867 //r = (dir ? 1.0f : brighten)/(range*2+1);
2868 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2869 GL_Color(r, r, r, 1);
2870 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2871 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2872 GL_BlendFunc(GL_ONE, GL_ONE);
2875 // copy the vertically blurred bloom view to a texture
2876 GL_ActiveTexture(0);
2878 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
2879 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2882 // apply subtract last
2883 // (just like it would be in a GLSL shader)
2884 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2886 GL_BlendFunc(GL_ONE, GL_ZERO);
2887 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2888 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2889 GL_Color(1, 1, 1, 1);
2890 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2891 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2893 GL_BlendFunc(GL_ONE, GL_ONE);
2894 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2895 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2896 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2897 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2898 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2899 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2900 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2902 // copy the darkened bloom view to a texture
2903 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2904 GL_ActiveTexture(0);
2906 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
2907 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2911 void R_HDR_RenderBloomTexture(void)
2913 int oldwidth, oldheight;
2915 oldwidth = r_view.width;
2916 oldheight = r_view.height;
2917 r_view.width = r_bloomstate.bloomwidth;
2918 r_view.height = r_bloomstate.bloomheight;
2920 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2921 // TODO: add exposure compensation features
2922 // TODO: add fp16 framebuffer support
2924 r_view.showdebug = false;
2925 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2927 r_view.colorscale /= r_hdr_range.value;
2928 r_waterstate.numwaterplanes = 0;
2929 R_RenderScene(r_waterstate.enabled);
2930 r_view.showdebug = true;
2932 R_ResetViewRendering2D();
2934 R_Bloom_CopyHDRTexture();
2935 R_Bloom_MakeTexture();
2937 R_ResetViewRendering3D();
2940 if (r_timereport_active)
2941 R_TimeReport("clear");
2944 // restore the view settings
2945 r_view.width = oldwidth;
2946 r_view.height = oldheight;
2949 static void R_BlendView(void)
2951 if (r_bloomstate.enabled && r_bloomstate.hdr)
2953 // render high dynamic range bloom effect
2954 // the bloom texture was made earlier this render, so we just need to
2955 // blend it onto the screen...
2956 R_ResetViewRendering2D();
2957 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2958 R_Mesh_ColorPointer(NULL, 0, 0);
2959 GL_Color(1, 1, 1, 1);
2960 GL_BlendFunc(GL_ONE, GL_ONE);
2961 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2962 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2963 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2964 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2966 else if (r_bloomstate.enabled)
2968 // render simple bloom effect
2969 // copy the screen and shrink it and darken it for the bloom process
2970 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2971 // make the bloom texture
2972 R_Bloom_MakeTexture();
2973 // put the original screen image back in place and blend the bloom
2975 R_ResetViewRendering2D();
2976 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2977 R_Mesh_ColorPointer(NULL, 0, 0);
2978 GL_Color(1, 1, 1, 1);
2979 GL_BlendFunc(GL_ONE, GL_ZERO);
2980 // do both in one pass if possible
2981 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2982 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2983 if (r_textureunits.integer >= 2 && gl_combine.integer)
2985 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2986 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2987 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2991 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2992 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2993 // now blend on the bloom texture
2994 GL_BlendFunc(GL_ONE, GL_ONE);
2995 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2996 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2998 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2999 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3001 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3003 // apply a color tint to the whole view
3004 R_ResetViewRendering2D();
3005 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3006 R_Mesh_ColorPointer(NULL, 0, 0);
3007 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3008 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3009 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3013 void R_RenderScene(qboolean addwaterplanes);
3015 matrix4x4_t r_waterscrollmatrix;
3017 void R_UpdateVariables(void)
3021 r_refdef.farclip = 4096;
3022 if (r_refdef.worldmodel)
3023 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3024 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3026 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3027 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3028 r_refdef.polygonfactor = 0;
3029 r_refdef.polygonoffset = 0;
3030 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3031 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3033 r_refdef.rtworld = r_shadow_realtime_world.integer;
3034 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3035 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3036 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3037 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3038 if (r_showsurfaces.integer)
3040 r_refdef.rtworld = false;
3041 r_refdef.rtworldshadows = false;
3042 r_refdef.rtdlight = false;
3043 r_refdef.rtdlightshadows = false;
3044 r_refdef.lightmapintensity = 0;
3047 if (gamemode == GAME_NEHAHRA)
3049 if (gl_fogenable.integer)
3051 r_refdef.oldgl_fogenable = true;
3052 r_refdef.fog_density = gl_fogdensity.value;
3053 r_refdef.fog_red = gl_fogred.value;
3054 r_refdef.fog_green = gl_foggreen.value;
3055 r_refdef.fog_blue = gl_fogblue.value;
3057 else if (r_refdef.oldgl_fogenable)
3059 r_refdef.oldgl_fogenable = false;
3060 r_refdef.fog_density = 0;
3061 r_refdef.fog_red = 0;
3062 r_refdef.fog_green = 0;
3063 r_refdef.fog_blue = 0;
3066 if (r_refdef.fog_density)
3068 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3069 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3070 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3072 if (r_refdef.fog_density)
3074 r_refdef.fogenabled = true;
3075 // this is the point where the fog reaches 0.9986 alpha, which we
3076 // consider a good enough cutoff point for the texture
3077 // (0.9986 * 256 == 255.6)
3078 r_refdef.fogrange = 400 / r_refdef.fog_density;
3079 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3080 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3081 // fog color was already set
3084 r_refdef.fogenabled = false;
3092 void R_RenderView(void)
3094 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3095 return; //Host_Error ("R_RenderView: NULL worldmodel");
3097 R_Shadow_UpdateWorldLightSelection();
3099 R_Bloom_StartFrame();
3100 R_Water_StartFrame();
3103 if (r_timereport_active)
3104 R_TimeReport("setup");
3106 R_ResetViewRendering3D();
3109 if (r_timereport_active)
3110 R_TimeReport("clear");
3112 r_view.showdebug = true;
3114 // this produces a bloom texture to be used in R_BlendView() later
3116 R_HDR_RenderBloomTexture();
3118 r_view.colorscale = r_hdr_scenebrightness.value;
3119 r_waterstate.numwaterplanes = 0;
3120 R_RenderScene(r_waterstate.enabled);
3123 if (r_timereport_active)
3124 R_TimeReport("blendview");
3126 GL_Scissor(0, 0, vid.width, vid.height);
3127 GL_ScissorTest(false);
3131 extern void R_DrawLightningBeams (void);
3132 extern void VM_CL_AddPolygonsToMeshQueue (void);
3133 extern void R_DrawPortals (void);
3134 extern cvar_t cl_locs_show;
3135 static void R_DrawLocs(void);
3136 static void R_DrawEntityBBoxes(void);
3137 void R_RenderScene(qboolean addwaterplanes)
3141 R_ResetViewRendering3D();
3144 if (r_timereport_active)
3145 R_TimeReport("watervisibility");
3147 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3149 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3150 if (r_timereport_active)
3151 R_TimeReport("waterworld");
3154 // don't let sound skip if going slow
3155 if (r_refdef.extraupdate)
3158 R_DrawModelsAddWaterPlanes();
3159 if (r_timereport_active)
3160 R_TimeReport("watermodels");
3162 R_Water_ProcessPlanes();
3163 if (r_timereport_active)
3164 R_TimeReport("waterscenes");
3167 R_ResetViewRendering3D();
3169 // don't let sound skip if going slow
3170 if (r_refdef.extraupdate)
3173 R_MeshQueue_BeginScene();
3178 if (r_timereport_active)
3179 R_TimeReport("visibility");
3181 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);
3183 if (cl.csqc_vidvars.drawworld)
3185 // don't let sound skip if going slow
3186 if (r_refdef.extraupdate)
3189 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3191 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3192 if (r_timereport_active)
3193 R_TimeReport("worldsky");
3196 if (R_DrawBrushModelsSky() && r_timereport_active)
3197 R_TimeReport("bmodelsky");
3200 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3202 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3203 if (r_timereport_active)
3204 R_TimeReport("worlddepth");
3206 if (r_depthfirst.integer >= 2)
3208 R_DrawModelsDepth();
3209 if (r_timereport_active)
3210 R_TimeReport("modeldepth");
3213 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3215 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3216 if (r_timereport_active)
3217 R_TimeReport("world");
3220 // don't let sound skip if going slow
3221 if (r_refdef.extraupdate)
3225 if (r_timereport_active)
3226 R_TimeReport("models");
3228 // don't let sound skip if going slow
3229 if (r_refdef.extraupdate)
3232 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3234 R_DrawModelShadows();
3236 R_ResetViewRendering3D();
3238 // don't let sound skip if going slow
3239 if (r_refdef.extraupdate)
3243 R_ShadowVolumeLighting(false);
3244 if (r_timereport_active)
3245 R_TimeReport("rtlights");
3247 // don't let sound skip if going slow
3248 if (r_refdef.extraupdate)
3251 if (cl.csqc_vidvars.drawworld)
3253 R_DrawLightningBeams();
3254 if (r_timereport_active)
3255 R_TimeReport("lightning");
3258 if (r_timereport_active)
3259 R_TimeReport("particles");
3262 if (r_timereport_active)
3263 R_TimeReport("explosions");
3266 if (gl_support_fragment_shader)
3268 qglUseProgramObjectARB(0);CHECKGLERROR
3270 VM_CL_AddPolygonsToMeshQueue();
3272 if (r_view.showdebug)
3274 if (cl_locs_show.integer)
3277 if (r_timereport_active)
3278 R_TimeReport("showlocs");
3281 if (r_drawportals.integer)
3284 if (r_timereport_active)
3285 R_TimeReport("portals");
3288 if (r_showbboxes.value > 0)
3290 R_DrawEntityBBoxes();
3291 if (r_timereport_active)
3292 R_TimeReport("bboxes");
3296 if (gl_support_fragment_shader)
3298 qglUseProgramObjectARB(0);CHECKGLERROR
3300 R_MeshQueue_RenderTransparent();
3301 if (r_timereport_active)
3302 R_TimeReport("drawtrans");
3304 if (gl_support_fragment_shader)
3306 qglUseProgramObjectARB(0);CHECKGLERROR
3309 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3311 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3312 if (r_timereport_active)
3313 R_TimeReport("worlddebug");
3314 R_DrawModelsDebug();
3315 if (r_timereport_active)
3316 R_TimeReport("modeldebug");
3319 if (gl_support_fragment_shader)
3321 qglUseProgramObjectARB(0);CHECKGLERROR
3324 if (cl.csqc_vidvars.drawworld)
3327 if (r_timereport_active)
3328 R_TimeReport("coronas");
3331 // don't let sound skip if going slow
3332 if (r_refdef.extraupdate)
3335 R_ResetViewRendering2D();
3338 static const int bboxelements[36] =
3348 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3351 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3352 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3353 GL_DepthMask(false);
3354 GL_DepthRange(0, 1);
3355 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3356 R_Mesh_Matrix(&identitymatrix);
3357 R_Mesh_ResetTextureState();
3359 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3360 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3361 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3362 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3363 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3364 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3365 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3366 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3367 R_FillColors(color4f, 8, cr, cg, cb, ca);
3368 if (r_refdef.fogenabled)
3370 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3372 f1 = FogPoint_World(v);
3374 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3375 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3376 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3379 R_Mesh_VertexPointer(vertex3f, 0, 0);
3380 R_Mesh_ColorPointer(color4f, 0, 0);
3381 R_Mesh_ResetTextureState();
3382 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3385 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3389 prvm_edict_t *edict;
3390 // this function draws bounding boxes of server entities
3394 for (i = 0;i < numsurfaces;i++)
3396 edict = PRVM_EDICT_NUM(surfacelist[i]);
3397 switch ((int)edict->fields.server->solid)
3399 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3400 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3401 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3402 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3403 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3404 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3406 color[3] *= r_showbboxes.value;
3407 color[3] = bound(0, color[3], 1);
3408 GL_DepthTest(!r_showdisabledepthtest.integer);
3409 GL_CullFace(r_view.cullface_front);
3410 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3415 static void R_DrawEntityBBoxes(void)
3418 prvm_edict_t *edict;
3420 // this function draws bounding boxes of server entities
3424 for (i = 0;i < prog->num_edicts;i++)
3426 edict = PRVM_EDICT_NUM(i);
3427 if (edict->priv.server->free)
3429 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3430 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3435 int nomodelelements[24] =
3447 float nomodelvertex3f[6*3] =
3457 float nomodelcolor4f[6*4] =
3459 0.0f, 0.0f, 0.5f, 1.0f,
3460 0.0f, 0.0f, 0.5f, 1.0f,
3461 0.0f, 0.5f, 0.0f, 1.0f,
3462 0.0f, 0.5f, 0.0f, 1.0f,
3463 0.5f, 0.0f, 0.0f, 1.0f,
3464 0.5f, 0.0f, 0.0f, 1.0f
3467 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3472 // this is only called once per entity so numsurfaces is always 1, and
3473 // surfacelist is always {0}, so this code does not handle batches
3474 R_Mesh_Matrix(&ent->matrix);
3476 if (ent->flags & EF_ADDITIVE)
3478 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3479 GL_DepthMask(false);
3481 else if (ent->alpha < 1)
3483 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3484 GL_DepthMask(false);
3488 GL_BlendFunc(GL_ONE, GL_ZERO);
3491 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3492 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3493 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3494 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3495 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3496 if (r_refdef.fogenabled)
3499 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3500 R_Mesh_ColorPointer(color4f, 0, 0);
3501 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3502 f1 = FogPoint_World(org);
3504 for (i = 0, c = color4f;i < 6;i++, c += 4)
3506 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3507 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3508 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3512 else if (ent->alpha != 1)
3514 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3515 R_Mesh_ColorPointer(color4f, 0, 0);
3516 for (i = 0, c = color4f;i < 6;i++, c += 4)
3520 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3521 R_Mesh_ResetTextureState();
3522 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3525 void R_DrawNoModel(entity_render_t *ent)
3528 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3529 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3530 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3532 // R_DrawNoModelCallback(ent, 0);
3535 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3537 vec3_t right1, right2, diff, normal;
3539 VectorSubtract (org2, org1, normal);
3541 // calculate 'right' vector for start
3542 VectorSubtract (r_view.origin, org1, diff);
3543 CrossProduct (normal, diff, right1);
3544 VectorNormalize (right1);
3546 // calculate 'right' vector for end
3547 VectorSubtract (r_view.origin, org2, diff);
3548 CrossProduct (normal, diff, right2);
3549 VectorNormalize (right2);
3551 vert[ 0] = org1[0] + width * right1[0];
3552 vert[ 1] = org1[1] + width * right1[1];
3553 vert[ 2] = org1[2] + width * right1[2];
3554 vert[ 3] = org1[0] - width * right1[0];
3555 vert[ 4] = org1[1] - width * right1[1];
3556 vert[ 5] = org1[2] - width * right1[2];
3557 vert[ 6] = org2[0] - width * right2[0];
3558 vert[ 7] = org2[1] - width * right2[1];
3559 vert[ 8] = org2[2] - width * right2[2];
3560 vert[ 9] = org2[0] + width * right2[0];
3561 vert[10] = org2[1] + width * right2[1];
3562 vert[11] = org2[2] + width * right2[2];
3565 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3567 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)
3572 if (r_refdef.fogenabled)
3573 fog = FogPoint_World(origin);
3575 R_Mesh_Matrix(&identitymatrix);
3576 GL_BlendFunc(blendfunc1, blendfunc2);
3582 GL_CullFace(r_view.cullface_front);
3585 GL_CullFace(r_view.cullface_back);
3587 GL_DepthMask(false);
3588 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3589 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3590 GL_DepthTest(!depthdisable);
3592 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3593 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3594 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3595 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3596 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3597 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3598 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3599 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3600 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3601 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3602 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3603 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3605 R_Mesh_VertexPointer(vertex3f, 0, 0);
3606 R_Mesh_ColorPointer(NULL, 0, 0);
3607 R_Mesh_ResetTextureState();
3608 R_Mesh_TexBind(0, R_GetTexture(texture));
3609 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3610 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3611 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3612 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3614 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3616 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3617 GL_BlendFunc(blendfunc1, GL_ONE);
3619 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);
3620 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3624 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3629 VectorSet(v, x, y, z);
3630 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3631 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3633 if (i == mesh->numvertices)
3635 if (mesh->numvertices < mesh->maxvertices)
3637 VectorCopy(v, vertex3f);
3638 mesh->numvertices++;
3640 return mesh->numvertices;
3646 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3650 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3651 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3652 e = mesh->element3i + mesh->numtriangles * 3;
3653 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3655 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3656 if (mesh->numtriangles < mesh->maxtriangles)
3661 mesh->numtriangles++;
3663 element[1] = element[2];
3667 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3671 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3672 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3673 e = mesh->element3i + mesh->numtriangles * 3;
3674 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3676 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3677 if (mesh->numtriangles < mesh->maxtriangles)
3682 mesh->numtriangles++;
3684 element[1] = element[2];
3688 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3689 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3691 int planenum, planenum2;
3694 mplane_t *plane, *plane2;
3696 double temppoints[2][256*3];
3697 // figure out how large a bounding box we need to properly compute this brush
3699 for (w = 0;w < numplanes;w++)
3700 maxdist = max(maxdist, planes[w].dist);
3701 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3702 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3703 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3707 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3708 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3710 if (planenum2 == planenum)
3712 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);
3715 if (tempnumpoints < 3)
3717 // generate elements forming a triangle fan for this polygon
3718 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3722 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)
3724 texturelayer_t *layer;
3725 layer = t->currentlayers + t->currentnumlayers++;
3727 layer->depthmask = depthmask;
3728 layer->blendfunc1 = blendfunc1;
3729 layer->blendfunc2 = blendfunc2;
3730 layer->texture = texture;
3731 layer->texmatrix = *matrix;
3732 layer->color[0] = r * r_view.colorscale;
3733 layer->color[1] = g * r_view.colorscale;
3734 layer->color[2] = b * r_view.colorscale;
3735 layer->color[3] = a;
3738 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3741 index = parms[2] + r_refdef.time * parms[3];
3742 index -= floor(index);
3746 case Q3WAVEFUNC_NONE:
3747 case Q3WAVEFUNC_NOISE:
3748 case Q3WAVEFUNC_COUNT:
3751 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3752 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3753 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3754 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3755 case Q3WAVEFUNC_TRIANGLE:
3757 f = index - floor(index);
3768 return (float)(parms[0] + parms[1] * f);
3771 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3774 model_t *model = ent->model;
3777 q3shaderinfo_layer_tcmod_t *tcmod;
3779 // switch to an alternate material if this is a q1bsp animated material
3781 texture_t *texture = t;
3782 int s = ent->skinnum;
3783 if ((unsigned int)s >= (unsigned int)model->numskins)
3785 if (model->skinscenes)
3787 if (model->skinscenes[s].framecount > 1)
3788 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3790 s = model->skinscenes[s].firstframe;
3793 t = t + s * model->num_surfaces;
3796 // use an alternate animation if the entity's frame is not 0,
3797 // and only if the texture has an alternate animation
3798 if (ent->frame2 != 0 && t->anim_total[1])
3799 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3801 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3803 texture->currentframe = t;
3806 // update currentskinframe to be a qw skin or animation frame
3807 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3809 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3811 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3812 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3813 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);
3815 t->currentskinframe = r_qwskincache_skinframe[i];
3816 if (t->currentskinframe == NULL)
3817 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3819 else if (t->numskinframes >= 2)
3820 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3821 if (t->backgroundnumskinframes >= 2)
3822 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3824 t->currentmaterialflags = t->basematerialflags;
3825 t->currentalpha = ent->alpha;
3826 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3828 t->currentalpha *= r_wateralpha.value;
3829 // if rendering refraction/reflection, disable transparency
3830 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3831 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3833 if (!(ent->flags & RENDER_LIGHT))
3834 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3835 if (ent->effects & EF_ADDITIVE)
3836 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3837 else if (t->currentalpha < 1)
3838 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3839 if (ent->effects & EF_DOUBLESIDED)
3840 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3841 if (ent->effects & EF_NODEPTHTEST)
3842 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3843 if (ent->flags & RENDER_VIEWMODEL)
3844 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3845 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3846 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3847 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3848 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3850 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3853 switch(tcmod->tcmod)
3857 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3858 matrix = r_waterscrollmatrix;
3860 matrix = identitymatrix;
3862 case Q3TCMOD_ENTITYTRANSLATE:
3863 // this is used in Q3 to allow the gamecode to control texcoord
3864 // scrolling on the entity, which is not supported in darkplaces yet.
3865 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3867 case Q3TCMOD_ROTATE:
3868 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3869 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3870 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3873 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3875 case Q3TCMOD_SCROLL:
3876 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3878 case Q3TCMOD_STRETCH:
3879 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3880 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3882 case Q3TCMOD_TRANSFORM:
3883 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3884 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3885 VectorSet(tcmat + 6, 0 , 0 , 1);
3886 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3887 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3889 case Q3TCMOD_TURBULENT:
3890 // this is handled in the RSurf_PrepareVertices function
3891 matrix = identitymatrix;
3894 // either replace or concatenate the transformation
3896 t->currenttexmatrix = matrix;
3899 matrix4x4_t temp = t->currenttexmatrix;
3900 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3904 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3905 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3906 t->glosstexture = r_texture_black;
3907 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3908 t->backgroundglosstexture = r_texture_black;
3909 t->specularpower = r_shadow_glossexponent.value;
3910 // TODO: store reference values for these in the texture?
3911 t->specularscale = 0;
3912 if (r_shadow_gloss.integer > 0)
3914 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3916 if (r_shadow_glossintensity.value > 0)
3918 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3919 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3920 t->specularscale = r_shadow_glossintensity.value;
3923 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3925 t->glosstexture = r_texture_white;
3926 t->backgroundglosstexture = r_texture_white;
3927 t->specularscale = r_shadow_gloss2intensity.value;
3931 // lightmaps mode looks bad with dlights using actual texturing, so turn
3932 // off the colormap and glossmap, but leave the normalmap on as it still
3933 // accurately represents the shading involved
3934 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3936 t->basetexture = r_texture_white;
3937 t->specularscale = 0;
3940 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3941 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3942 // submodels are biased to avoid z-fighting with world surfaces that they
3943 // may be exactly overlapping (avoids z-fighting artifacts on certain
3944 // doors and things in Quake maps)
3945 if (ent->model->brush.submodel)
3947 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3948 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3951 VectorClear(t->dlightcolor);
3952 t->currentnumlayers = 0;
3953 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3955 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3957 int blendfunc1, blendfunc2, depthmask;
3958 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3960 blendfunc1 = GL_SRC_ALPHA;
3961 blendfunc2 = GL_ONE;
3963 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3965 blendfunc1 = GL_SRC_ALPHA;
3966 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3968 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3970 blendfunc1 = t->customblendfunc[0];
3971 blendfunc2 = t->customblendfunc[1];
3975 blendfunc1 = GL_ONE;
3976 blendfunc2 = GL_ZERO;
3978 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3979 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3981 rtexture_t *currentbasetexture;
3983 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3984 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3985 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3986 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3988 // fullbright is not affected by r_refdef.lightmapintensity
3989 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3990 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3991 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);
3992 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3993 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);
3998 // set the color tint used for lights affecting this surface
3999 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4001 // q3bsp has no lightmap updates, so the lightstylevalue that
4002 // would normally be baked into the lightmap must be
4003 // applied to the color
4004 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4005 if (ent->model->type == mod_brushq3)
4006 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4007 colorscale *= r_refdef.lightmapintensity;
4008 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);
4009 if (r_ambient.value >= (1.0f/64.0f))
4010 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);
4011 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4013 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);
4014 if (r_ambient.value >= (1.0f/64.0f))
4015 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);
4017 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4019 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);
4020 if (r_ambient.value >= (1.0f/64.0f))
4021 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);
4024 if (t->currentskinframe->glow != NULL)
4025 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);
4026 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4028 // if this is opaque use alpha blend which will darken the earlier
4031 // if this is an alpha blended material, all the earlier passes
4032 // were darkened by fog already, so we only need to add the fog
4033 // color ontop through the fog mask texture
4035 // if this is an additive blended material, all the earlier passes
4036 // were darkened by fog already, and we should not add fog color
4037 // (because the background was not darkened, there is no fog color
4038 // that was lost behind it).
4039 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);
4046 void R_UpdateAllTextureInfo(entity_render_t *ent)
4050 for (i = 0;i < ent->model->num_texturesperskin;i++)
4051 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4054 rsurfacestate_t rsurface;
4056 void R_Mesh_ResizeArrays(int newvertices)
4059 if (rsurface.array_size >= newvertices)
4061 if (rsurface.array_modelvertex3f)
4062 Mem_Free(rsurface.array_modelvertex3f);
4063 rsurface.array_size = (newvertices + 1023) & ~1023;
4064 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4065 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4066 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4067 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4068 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4069 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4070 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4071 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4072 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4073 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4074 rsurface.array_color4f = base + rsurface.array_size * 27;
4075 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4078 void RSurf_CleanUp(void)
4081 if (rsurface.mode == RSURFMODE_GLSL)
4083 qglUseProgramObjectARB(0);CHECKGLERROR
4085 GL_AlphaTest(false);
4086 rsurface.mode = RSURFMODE_NONE;
4087 rsurface.uselightmaptexture = false;
4088 rsurface.texture = NULL;
4091 void RSurf_ActiveWorldEntity(void)
4093 model_t *model = r_refdef.worldmodel;
4095 if (rsurface.array_size < model->surfmesh.num_vertices)
4096 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4097 rsurface.matrix = identitymatrix;
4098 rsurface.inversematrix = identitymatrix;
4099 R_Mesh_Matrix(&identitymatrix);
4100 VectorCopy(r_view.origin, rsurface.modelorg);
4101 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4102 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4103 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4104 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4105 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4106 rsurface.frameblend[0].frame = 0;
4107 rsurface.frameblend[0].lerp = 1;
4108 rsurface.frameblend[1].frame = 0;
4109 rsurface.frameblend[1].lerp = 0;
4110 rsurface.frameblend[2].frame = 0;
4111 rsurface.frameblend[2].lerp = 0;
4112 rsurface.frameblend[3].frame = 0;
4113 rsurface.frameblend[3].lerp = 0;
4114 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4115 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4116 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4117 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4118 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4119 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4120 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4121 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4122 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4123 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4124 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4125 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4126 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4127 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4128 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4129 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4130 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4131 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4132 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4133 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4134 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4135 rsurface.modelelement3i = model->surfmesh.data_element3i;
4136 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4137 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4138 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4139 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4140 rsurface.modelsurfaces = model->data_surfaces;
4141 rsurface.generatedvertex = false;
4142 rsurface.vertex3f = rsurface.modelvertex3f;
4143 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4144 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4145 rsurface.svector3f = rsurface.modelsvector3f;
4146 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4147 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4148 rsurface.tvector3f = rsurface.modeltvector3f;
4149 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4150 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4151 rsurface.normal3f = rsurface.modelnormal3f;
4152 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4153 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4154 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4157 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4159 model_t *model = ent->model;
4161 if (rsurface.array_size < model->surfmesh.num_vertices)
4162 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4163 rsurface.matrix = ent->matrix;
4164 rsurface.inversematrix = ent->inversematrix;
4165 R_Mesh_Matrix(&rsurface.matrix);
4166 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4167 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4168 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4169 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4170 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4171 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4172 rsurface.frameblend[0] = ent->frameblend[0];
4173 rsurface.frameblend[1] = ent->frameblend[1];
4174 rsurface.frameblend[2] = ent->frameblend[2];
4175 rsurface.frameblend[3] = ent->frameblend[3];
4176 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4180 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4181 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4182 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4183 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4184 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4186 else if (wantnormals)
4188 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4189 rsurface.modelsvector3f = NULL;
4190 rsurface.modeltvector3f = NULL;
4191 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4192 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4196 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4197 rsurface.modelsvector3f = NULL;
4198 rsurface.modeltvector3f = NULL;
4199 rsurface.modelnormal3f = NULL;
4200 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4202 rsurface.modelvertex3f_bufferobject = 0;
4203 rsurface.modelvertex3f_bufferoffset = 0;
4204 rsurface.modelsvector3f_bufferobject = 0;
4205 rsurface.modelsvector3f_bufferoffset = 0;
4206 rsurface.modeltvector3f_bufferobject = 0;
4207 rsurface.modeltvector3f_bufferoffset = 0;
4208 rsurface.modelnormal3f_bufferobject = 0;
4209 rsurface.modelnormal3f_bufferoffset = 0;
4210 rsurface.generatedvertex = true;
4214 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4215 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4216 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4217 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4218 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4219 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4220 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4221 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4222 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4223 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4224 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4225 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4226 rsurface.generatedvertex = false;
4228 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4229 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4230 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4231 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4232 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4233 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4234 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4235 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4236 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4237 rsurface.modelelement3i = model->surfmesh.data_element3i;
4238 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4239 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4240 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4241 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4242 rsurface.modelsurfaces = model->data_surfaces;
4243 rsurface.vertex3f = rsurface.modelvertex3f;
4244 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4245 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4246 rsurface.svector3f = rsurface.modelsvector3f;
4247 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4248 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4249 rsurface.tvector3f = rsurface.modeltvector3f;
4250 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4251 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4252 rsurface.normal3f = rsurface.modelnormal3f;
4253 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4254 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4255 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4258 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4259 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4262 int texturesurfaceindex;
4267 const float *v1, *in_tc;
4269 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4271 q3shaderinfo_deform_t *deform;
4272 // 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
4273 if (rsurface.generatedvertex)
4275 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4276 generatenormals = true;
4277 for (i = 0;i < Q3MAXDEFORMS;i++)
4279 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4281 generatetangents = true;
4282 generatenormals = true;
4284 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4285 generatenormals = true;
4287 if (generatenormals && !rsurface.modelnormal3f)
4289 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4290 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4291 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4292 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4294 if (generatetangents && !rsurface.modelsvector3f)
4296 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4297 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4298 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4299 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4300 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4301 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4302 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);
4305 rsurface.vertex3f = rsurface.modelvertex3f;
4306 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4307 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4308 rsurface.svector3f = rsurface.modelsvector3f;
4309 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4310 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4311 rsurface.tvector3f = rsurface.modeltvector3f;
4312 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4313 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4314 rsurface.normal3f = rsurface.modelnormal3f;
4315 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4316 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4317 // if vertices are deformed (sprite flares and things in maps, possibly
4318 // water waves, bulges and other deformations), generate them into
4319 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4320 // (may be static model data or generated data for an animated model, or
4321 // the previous deform pass)
4322 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4324 switch (deform->deform)
4327 case Q3DEFORM_PROJECTIONSHADOW:
4328 case Q3DEFORM_TEXT0:
4329 case Q3DEFORM_TEXT1:
4330 case Q3DEFORM_TEXT2:
4331 case Q3DEFORM_TEXT3:
4332 case Q3DEFORM_TEXT4:
4333 case Q3DEFORM_TEXT5:
4334 case Q3DEFORM_TEXT6:
4335 case Q3DEFORM_TEXT7:
4338 case Q3DEFORM_AUTOSPRITE:
4339 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4340 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4341 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4342 VectorNormalize(newforward);
4343 VectorNormalize(newright);
4344 VectorNormalize(newup);
4345 // make deformed versions of only the model vertices used by the specified surfaces
4346 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4348 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4349 // a single autosprite surface can contain multiple sprites...
4350 for (j = 0;j < surface->num_vertices - 3;j += 4)
4352 VectorClear(center);
4353 for (i = 0;i < 4;i++)
4354 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4355 VectorScale(center, 0.25f, center);
4356 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4357 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4358 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4359 for (i = 0;i < 4;i++)
4361 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4362 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4365 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);
4366 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);
4368 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4369 rsurface.vertex3f_bufferobject = 0;
4370 rsurface.vertex3f_bufferoffset = 0;
4371 rsurface.svector3f = rsurface.array_deformedsvector3f;
4372 rsurface.svector3f_bufferobject = 0;
4373 rsurface.svector3f_bufferoffset = 0;
4374 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4375 rsurface.tvector3f_bufferobject = 0;
4376 rsurface.tvector3f_bufferoffset = 0;
4377 rsurface.normal3f = rsurface.array_deformednormal3f;
4378 rsurface.normal3f_bufferobject = 0;
4379 rsurface.normal3f_bufferoffset = 0;
4381 case Q3DEFORM_AUTOSPRITE2:
4382 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4383 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4384 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4385 VectorNormalize(newforward);
4386 VectorNormalize(newright);
4387 VectorNormalize(newup);
4388 // make deformed versions of only the model vertices used by the specified surfaces
4389 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4391 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4392 const float *v1, *v2;
4402 memset(shortest, 0, sizeof(shortest));
4403 // a single autosprite surface can contain multiple sprites...
4404 for (j = 0;j < surface->num_vertices - 3;j += 4)
4406 VectorClear(center);
4407 for (i = 0;i < 4;i++)
4408 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4409 VectorScale(center, 0.25f, center);
4410 // find the two shortest edges, then use them to define the
4411 // axis vectors for rotating around the central axis
4412 for (i = 0;i < 6;i++)
4414 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4415 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4417 Debug_PolygonBegin(NULL, 0, false, 0);
4418 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4419 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);
4420 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4423 l = VectorDistance2(v1, v2);
4424 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4426 l += (1.0f / 1024.0f);
4427 if (shortest[0].length2 > l || i == 0)
4429 shortest[1] = shortest[0];
4430 shortest[0].length2 = l;
4431 shortest[0].v1 = v1;
4432 shortest[0].v2 = v2;
4434 else if (shortest[1].length2 > l || i == 1)
4436 shortest[1].length2 = l;
4437 shortest[1].v1 = v1;
4438 shortest[1].v2 = v2;
4441 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4442 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4444 Debug_PolygonBegin(NULL, 0, false, 0);
4445 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4446 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);
4447 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4450 // this calculates the right vector from the shortest edge
4451 // and the up vector from the edge midpoints
4452 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4453 VectorNormalize(right);
4454 VectorSubtract(end, start, up);
4455 VectorNormalize(up);
4456 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4457 //VectorSubtract(rsurface.modelorg, center, forward);
4458 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4459 VectorNegate(forward, forward);
4460 VectorReflect(forward, 0, up, forward);
4461 VectorNormalize(forward);
4462 CrossProduct(up, forward, newright);
4463 VectorNormalize(newright);
4465 Debug_PolygonBegin(NULL, 0, false, 0);
4466 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);
4467 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4468 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4472 Debug_PolygonBegin(NULL, 0, false, 0);
4473 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4474 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4475 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4478 // rotate the quad around the up axis vector, this is made
4479 // especially easy by the fact we know the quad is flat,
4480 // so we only have to subtract the center position and
4481 // measure distance along the right vector, and then
4482 // multiply that by the newright vector and add back the
4484 // we also need to subtract the old position to undo the
4485 // displacement from the center, which we do with a
4486 // DotProduct, the subtraction/addition of center is also
4487 // optimized into DotProducts here
4488 l = DotProduct(right, center);
4489 for (i = 0;i < 4;i++)
4491 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4492 f = DotProduct(right, v1) - l;
4493 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4496 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);
4497 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);
4499 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4500 rsurface.vertex3f_bufferobject = 0;
4501 rsurface.vertex3f_bufferoffset = 0;
4502 rsurface.svector3f = rsurface.array_deformedsvector3f;
4503 rsurface.svector3f_bufferobject = 0;
4504 rsurface.svector3f_bufferoffset = 0;
4505 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4506 rsurface.tvector3f_bufferobject = 0;
4507 rsurface.tvector3f_bufferoffset = 0;
4508 rsurface.normal3f = rsurface.array_deformednormal3f;
4509 rsurface.normal3f_bufferobject = 0;
4510 rsurface.normal3f_bufferoffset = 0;
4512 case Q3DEFORM_NORMAL:
4513 // deform the normals to make reflections wavey
4514 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4516 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4517 for (j = 0;j < surface->num_vertices;j++)
4520 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4521 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4522 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4523 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4524 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4525 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4526 VectorNormalize(normal);
4528 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);
4530 rsurface.svector3f = rsurface.array_deformedsvector3f;
4531 rsurface.svector3f_bufferobject = 0;
4532 rsurface.svector3f_bufferoffset = 0;
4533 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4534 rsurface.tvector3f_bufferobject = 0;
4535 rsurface.tvector3f_bufferoffset = 0;
4536 rsurface.normal3f = rsurface.array_deformednormal3f;
4537 rsurface.normal3f_bufferobject = 0;
4538 rsurface.normal3f_bufferoffset = 0;
4541 // deform vertex array to make wavey water and flags and such
4542 waveparms[0] = deform->waveparms[0];
4543 waveparms[1] = deform->waveparms[1];
4544 waveparms[2] = deform->waveparms[2];
4545 waveparms[3] = deform->waveparms[3];
4546 // this is how a divisor of vertex influence on deformation
4547 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4548 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4549 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4551 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4552 for (j = 0;j < surface->num_vertices;j++)
4554 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4555 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4556 // if the wavefunc depends on time, evaluate it per-vertex
4559 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4560 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4562 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4565 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4566 rsurface.vertex3f_bufferobject = 0;
4567 rsurface.vertex3f_bufferoffset = 0;
4569 case Q3DEFORM_BULGE:
4570 // deform vertex array to make the surface have moving bulges
4571 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4573 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4574 for (j = 0;j < surface->num_vertices;j++)
4576 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4577 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4580 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4581 rsurface.vertex3f_bufferobject = 0;
4582 rsurface.vertex3f_bufferoffset = 0;
4585 // deform vertex array
4586 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4587 VectorScale(deform->parms, scale, waveparms);
4588 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4590 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4591 for (j = 0;j < surface->num_vertices;j++)
4592 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4594 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4595 rsurface.vertex3f_bufferobject = 0;
4596 rsurface.vertex3f_bufferoffset = 0;
4600 // generate texcoords based on the chosen texcoord source
4601 switch(rsurface.texture->tcgen.tcgen)
4604 case Q3TCGEN_TEXTURE:
4605 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4606 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4607 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4609 case Q3TCGEN_LIGHTMAP:
4610 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4611 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4612 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4614 case Q3TCGEN_VECTOR:
4615 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4617 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4618 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)
4620 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4621 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4624 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4625 rsurface.texcoordtexture2f_bufferobject = 0;
4626 rsurface.texcoordtexture2f_bufferoffset = 0;
4628 case Q3TCGEN_ENVIRONMENT:
4629 // make environment reflections using a spheremap
4630 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4632 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4633 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4634 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4635 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4636 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4638 float l, d, eyedir[3];
4639 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4640 l = 0.5f / VectorLength(eyedir);
4641 d = DotProduct(normal, eyedir)*2;
4642 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4643 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4646 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4647 rsurface.texcoordtexture2f_bufferobject = 0;
4648 rsurface.texcoordtexture2f_bufferoffset = 0;
4651 // the only tcmod that needs software vertex processing is turbulent, so
4652 // check for it here and apply the changes if needed
4653 // and we only support that as the first one
4654 // (handling a mixture of turbulent and other tcmods would be problematic
4655 // without punting it entirely to a software path)
4656 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4658 amplitude = rsurface.texture->tcmods[0].parms[1];
4659 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4660 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4662 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4663 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)
4665 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4666 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4669 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4670 rsurface.texcoordtexture2f_bufferobject = 0;
4671 rsurface.texcoordtexture2f_bufferoffset = 0;
4673 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4674 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4675 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4676 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4679 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4682 const msurface_t *surface = texturesurfacelist[0];
4683 const msurface_t *surface2;
4688 // TODO: lock all array ranges before render, rather than on each surface
4689 if (texturenumsurfaces == 1)
4691 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4692 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));
4694 else if (r_batchmode.integer == 2)
4696 #define MAXBATCHTRIANGLES 4096
4697 int batchtriangles = 0;
4698 int batchelements[MAXBATCHTRIANGLES*3];
4699 for (i = 0;i < texturenumsurfaces;i = j)
4701 surface = texturesurfacelist[i];
4703 if (surface->num_triangles > MAXBATCHTRIANGLES)
4705 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));
4708 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4709 batchtriangles = surface->num_triangles;
4710 firstvertex = surface->num_firstvertex;
4711 endvertex = surface->num_firstvertex + surface->num_vertices;
4712 for (;j < texturenumsurfaces;j++)
4714 surface2 = texturesurfacelist[j];
4715 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4717 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4718 batchtriangles += surface2->num_triangles;
4719 firstvertex = min(firstvertex, surface2->num_firstvertex);
4720 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4722 surface2 = texturesurfacelist[j-1];
4723 numvertices = endvertex - firstvertex;
4724 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4727 else if (r_batchmode.integer == 1)
4729 for (i = 0;i < texturenumsurfaces;i = j)
4731 surface = texturesurfacelist[i];
4732 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4733 if (texturesurfacelist[j] != surface2)
4735 surface2 = texturesurfacelist[j-1];
4736 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4737 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4738 GL_LockArrays(surface->num_firstvertex, numvertices);
4739 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4744 for (i = 0;i < texturenumsurfaces;i++)
4746 surface = texturesurfacelist[i];
4747 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4748 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));
4753 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4755 int i, planeindex, vertexindex;
4759 r_waterstate_waterplane_t *p, *bestp;
4760 msurface_t *surface;
4761 if (r_waterstate.renderingscene)
4763 for (i = 0;i < texturenumsurfaces;i++)
4765 surface = texturesurfacelist[i];
4766 if (lightmaptexunit >= 0)
4767 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4768 if (deluxemaptexunit >= 0)
4769 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4770 // pick the closest matching water plane
4773 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4776 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4778 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4779 d += fabs(PlaneDiff(vert, &p->plane));
4781 if (bestd > d || !bestp)
4789 if (refractiontexunit >= 0)
4790 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4791 if (reflectiontexunit >= 0)
4792 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4796 if (refractiontexunit >= 0)
4797 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4798 if (reflectiontexunit >= 0)
4799 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4801 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4802 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));
4806 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4810 const msurface_t *surface = texturesurfacelist[0];
4811 const msurface_t *surface2;
4816 // TODO: lock all array ranges before render, rather than on each surface
4817 if (texturenumsurfaces == 1)
4819 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4820 if (deluxemaptexunit >= 0)
4821 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4822 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4823 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));
4825 else if (r_batchmode.integer == 2)
4827 #define MAXBATCHTRIANGLES 4096
4828 int batchtriangles = 0;
4829 int batchelements[MAXBATCHTRIANGLES*3];
4830 for (i = 0;i < texturenumsurfaces;i = j)
4832 surface = texturesurfacelist[i];
4833 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4834 if (deluxemaptexunit >= 0)
4835 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4837 if (surface->num_triangles > MAXBATCHTRIANGLES)
4839 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));
4842 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4843 batchtriangles = surface->num_triangles;
4844 firstvertex = surface->num_firstvertex;
4845 endvertex = surface->num_firstvertex + surface->num_vertices;
4846 for (;j < texturenumsurfaces;j++)
4848 surface2 = texturesurfacelist[j];
4849 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4851 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4852 batchtriangles += surface2->num_triangles;
4853 firstvertex = min(firstvertex, surface2->num_firstvertex);
4854 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4856 surface2 = texturesurfacelist[j-1];
4857 numvertices = endvertex - firstvertex;
4858 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4861 else if (r_batchmode.integer == 1)
4864 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4865 for (i = 0;i < texturenumsurfaces;i = j)
4867 surface = texturesurfacelist[i];
4868 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4869 if (texturesurfacelist[j] != surface2)
4871 Con_Printf(" %i", j - i);
4874 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4876 for (i = 0;i < texturenumsurfaces;i = j)
4878 surface = texturesurfacelist[i];
4879 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4880 if (deluxemaptexunit >= 0)
4881 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4882 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4883 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4886 Con_Printf(" %i", j - i);
4888 surface2 = texturesurfacelist[j-1];
4889 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4890 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4891 GL_LockArrays(surface->num_firstvertex, numvertices);
4892 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4900 for (i = 0;i < texturenumsurfaces;i++)
4902 surface = texturesurfacelist[i];
4903 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4904 if (deluxemaptexunit >= 0)
4905 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4906 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4907 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));
4912 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4915 int texturesurfaceindex;
4916 if (r_showsurfaces.integer == 2)
4918 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4920 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4921 for (j = 0;j < surface->num_triangles;j++)
4923 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4924 GL_Color(f, f, f, 1);
4925 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)));
4931 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4933 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4934 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4935 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);
4936 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4937 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));
4942 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4944 int texturesurfaceindex;
4948 if (rsurface.lightmapcolor4f)
4950 // generate color arrays for the surfaces in this list
4951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4953 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4954 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)
4956 f = FogPoint_Model(v);
4966 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4968 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4969 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)
4971 f = FogPoint_Model(v);
4979 rsurface.lightmapcolor4f = rsurface.array_color4f;
4980 rsurface.lightmapcolor4f_bufferobject = 0;
4981 rsurface.lightmapcolor4f_bufferoffset = 0;
4984 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4986 int texturesurfaceindex;
4989 if (!rsurface.lightmapcolor4f)
4991 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4993 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4994 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)
5002 rsurface.lightmapcolor4f = rsurface.array_color4f;
5003 rsurface.lightmapcolor4f_bufferobject = 0;
5004 rsurface.lightmapcolor4f_bufferoffset = 0;
5007 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5010 rsurface.lightmapcolor4f = NULL;
5011 rsurface.lightmapcolor4f_bufferobject = 0;
5012 rsurface.lightmapcolor4f_bufferoffset = 0;
5013 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5014 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5015 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5016 GL_Color(r, g, b, a);
5017 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5020 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5022 // TODO: optimize applyfog && applycolor case
5023 // just apply fog if necessary, and tint the fog color array if necessary
5024 rsurface.lightmapcolor4f = NULL;
5025 rsurface.lightmapcolor4f_bufferobject = 0;
5026 rsurface.lightmapcolor4f_bufferoffset = 0;
5027 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5028 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5029 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5030 GL_Color(r, g, b, a);
5031 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5034 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5036 int texturesurfaceindex;
5040 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5042 // generate color arrays for the surfaces in this list
5043 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5045 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5046 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5048 if (surface->lightmapinfo->samples)
5050 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5051 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5052 VectorScale(lm, scale, c);
5053 if (surface->lightmapinfo->styles[1] != 255)
5055 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5057 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5058 VectorMA(c, scale, lm, c);
5059 if (surface->lightmapinfo->styles[2] != 255)
5062 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5063 VectorMA(c, scale, lm, c);
5064 if (surface->lightmapinfo->styles[3] != 255)
5067 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5068 VectorMA(c, scale, lm, c);
5078 rsurface.lightmapcolor4f = rsurface.array_color4f;
5079 rsurface.lightmapcolor4f_bufferobject = 0;
5080 rsurface.lightmapcolor4f_bufferoffset = 0;
5084 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5085 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5086 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5088 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5089 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5090 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5091 GL_Color(r, g, b, a);
5092 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5095 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5097 int texturesurfaceindex;
5101 vec3_t ambientcolor;
5102 vec3_t diffusecolor;
5106 VectorCopy(rsurface.modellight_lightdir, lightdir);
5107 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5108 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5109 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5110 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5111 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5112 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5113 if (VectorLength2(diffusecolor) > 0)
5115 // generate color arrays for the surfaces in this list
5116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5118 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5119 int numverts = surface->num_vertices;
5120 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5121 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5122 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5123 // q3-style directional shading
5124 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5126 if ((f = DotProduct(c2, lightdir)) > 0)
5127 VectorMA(ambientcolor, f, diffusecolor, c);
5129 VectorCopy(ambientcolor, c);
5138 rsurface.lightmapcolor4f = rsurface.array_color4f;
5139 rsurface.lightmapcolor4f_bufferobject = 0;
5140 rsurface.lightmapcolor4f_bufferoffset = 0;
5144 r = ambientcolor[0];
5145 g = ambientcolor[1];
5146 b = ambientcolor[2];
5147 rsurface.lightmapcolor4f = NULL;
5148 rsurface.lightmapcolor4f_bufferobject = 0;
5149 rsurface.lightmapcolor4f_bufferoffset = 0;
5151 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5152 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5153 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5154 GL_Color(r, g, b, a);
5155 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5158 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5160 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5161 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5162 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5163 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5164 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5166 rsurface.mode = RSURFMODE_SHOWSURFACES;
5168 GL_BlendFunc(GL_ONE, GL_ZERO);
5169 R_Mesh_ColorPointer(NULL, 0, 0);
5170 R_Mesh_ResetTextureState();
5172 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5173 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5176 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5178 // transparent sky would be ridiculous
5179 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5181 if (rsurface.mode != RSURFMODE_SKY)
5183 if (rsurface.mode == RSURFMODE_GLSL)
5185 qglUseProgramObjectARB(0);CHECKGLERROR
5187 rsurface.mode = RSURFMODE_SKY;
5191 skyrendernow = false;
5193 // restore entity matrix
5194 R_Mesh_Matrix(&rsurface.matrix);
5196 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5197 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5198 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5199 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5201 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5202 // skymasking on them, and Quake3 never did sky masking (unlike
5203 // software Quake and software Quake2), so disable the sky masking
5204 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5205 // and skymasking also looks very bad when noclipping outside the
5206 // level, so don't use it then either.
5207 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5209 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5210 R_Mesh_ColorPointer(NULL, 0, 0);
5211 R_Mesh_ResetTextureState();
5212 if (skyrendermasked)
5214 // depth-only (masking)
5215 GL_ColorMask(0,0,0,0);
5216 // just to make sure that braindead drivers don't draw
5217 // anything despite that colormask...
5218 GL_BlendFunc(GL_ZERO, GL_ONE);
5223 GL_BlendFunc(GL_ONE, GL_ZERO);
5225 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5226 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5227 if (skyrendermasked)
5228 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5232 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5234 if (rsurface.mode != RSURFMODE_GLSL)
5236 rsurface.mode = RSURFMODE_GLSL;
5237 R_Mesh_ResetTextureState();
5240 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5241 if (!r_glsl_permutation)
5244 if (rsurface.lightmode == 2)
5245 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5247 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5248 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5249 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5250 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5251 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5252 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5254 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]);
5255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5257 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5258 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5259 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5260 R_Mesh_ColorPointer(NULL, 0, 0);
5262 else if (rsurface.uselightmaptexture)
5264 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5265 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5266 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5267 R_Mesh_ColorPointer(NULL, 0, 0);
5271 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5272 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5273 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5274 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5277 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5279 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5280 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5281 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5282 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5284 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5288 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5289 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5290 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5291 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5293 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5295 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5300 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5302 // OpenGL 1.3 path - anything not completely ancient
5303 int texturesurfaceindex;
5304 qboolean applycolor;
5308 const texturelayer_t *layer;
5309 if (rsurface.mode != RSURFMODE_MULTIPASS)
5310 rsurface.mode = RSURFMODE_MULTIPASS;
5311 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5312 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5315 int layertexrgbscale;
5316 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5318 if (layerindex == 0)
5322 GL_AlphaTest(false);
5323 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5326 GL_DepthMask(layer->depthmask);
5327 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5328 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5330 layertexrgbscale = 4;
5331 VectorScale(layer->color, 0.25f, layercolor);
5333 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5335 layertexrgbscale = 2;
5336 VectorScale(layer->color, 0.5f, layercolor);
5340 layertexrgbscale = 1;
5341 VectorScale(layer->color, 1.0f, layercolor);
5343 layercolor[3] = layer->color[3];
5344 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5345 R_Mesh_ColorPointer(NULL, 0, 0);
5346 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5347 switch (layer->type)
5349 case TEXTURELAYERTYPE_LITTEXTURE:
5350 memset(&m, 0, sizeof(m));
5351 m.tex[0] = R_GetTexture(r_texture_white);
5352 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5353 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5354 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5355 m.tex[1] = R_GetTexture(layer->texture);
5356 m.texmatrix[1] = layer->texmatrix;
5357 m.texrgbscale[1] = layertexrgbscale;
5358 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5359 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5360 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5361 R_Mesh_TextureState(&m);
5362 if (rsurface.lightmode == 2)
5363 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5364 else if (rsurface.uselightmaptexture)
5365 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5367 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5369 case TEXTURELAYERTYPE_TEXTURE:
5370 memset(&m, 0, sizeof(m));
5371 m.tex[0] = R_GetTexture(layer->texture);
5372 m.texmatrix[0] = layer->texmatrix;
5373 m.texrgbscale[0] = layertexrgbscale;
5374 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5375 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5376 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5377 R_Mesh_TextureState(&m);
5378 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5380 case TEXTURELAYERTYPE_FOG:
5381 memset(&m, 0, sizeof(m));
5382 m.texrgbscale[0] = layertexrgbscale;
5385 m.tex[0] = R_GetTexture(layer->texture);
5386 m.texmatrix[0] = layer->texmatrix;
5387 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5388 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5389 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5391 R_Mesh_TextureState(&m);
5392 // generate a color array for the fog pass
5393 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5394 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5398 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5399 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)
5401 f = 1 - FogPoint_Model(v);
5402 c[0] = layercolor[0];
5403 c[1] = layercolor[1];
5404 c[2] = layercolor[2];
5405 c[3] = f * layercolor[3];
5408 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5411 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5413 GL_LockArrays(0, 0);
5416 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5418 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5419 GL_AlphaTest(false);
5423 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5425 // OpenGL 1.1 - crusty old voodoo path
5426 int texturesurfaceindex;
5430 const texturelayer_t *layer;
5431 if (rsurface.mode != RSURFMODE_MULTIPASS)
5432 rsurface.mode = RSURFMODE_MULTIPASS;
5433 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5434 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5436 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5438 if (layerindex == 0)
5442 GL_AlphaTest(false);
5443 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5446 GL_DepthMask(layer->depthmask);
5447 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5448 R_Mesh_ColorPointer(NULL, 0, 0);
5449 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5450 switch (layer->type)
5452 case TEXTURELAYERTYPE_LITTEXTURE:
5453 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5455 // two-pass lit texture with 2x rgbscale
5456 // first the lightmap pass
5457 memset(&m, 0, sizeof(m));
5458 m.tex[0] = R_GetTexture(r_texture_white);
5459 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5460 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5461 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5462 R_Mesh_TextureState(&m);
5463 if (rsurface.lightmode == 2)
5464 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5465 else if (rsurface.uselightmaptexture)
5466 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5468 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5469 GL_LockArrays(0, 0);
5470 // then apply the texture to it
5471 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5472 memset(&m, 0, sizeof(m));
5473 m.tex[0] = R_GetTexture(layer->texture);
5474 m.texmatrix[0] = layer->texmatrix;
5475 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5476 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5477 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5478 R_Mesh_TextureState(&m);
5479 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);
5483 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5484 memset(&m, 0, sizeof(m));
5485 m.tex[0] = R_GetTexture(layer->texture);
5486 m.texmatrix[0] = layer->texmatrix;
5487 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5488 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5489 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5490 R_Mesh_TextureState(&m);
5491 if (rsurface.lightmode == 2)
5492 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);
5494 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);
5497 case TEXTURELAYERTYPE_TEXTURE:
5498 // singletexture unlit texture with transparency support
5499 memset(&m, 0, sizeof(m));
5500 m.tex[0] = R_GetTexture(layer->texture);
5501 m.texmatrix[0] = layer->texmatrix;
5502 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5503 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5504 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5505 R_Mesh_TextureState(&m);
5506 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);
5508 case TEXTURELAYERTYPE_FOG:
5509 // singletexture fogging
5510 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5513 memset(&m, 0, sizeof(m));
5514 m.tex[0] = R_GetTexture(layer->texture);
5515 m.texmatrix[0] = layer->texmatrix;
5516 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5517 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5518 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5519 R_Mesh_TextureState(&m);
5522 R_Mesh_ResetTextureState();
5523 // generate a color array for the fog pass
5524 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5528 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5529 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)
5531 f = 1 - FogPoint_Model(v);
5532 c[0] = layer->color[0];
5533 c[1] = layer->color[1];
5534 c[2] = layer->color[2];
5535 c[3] = f * layer->color[3];
5538 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5541 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5543 GL_LockArrays(0, 0);
5546 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5548 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5549 GL_AlphaTest(false);
5553 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5555 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5557 rsurface.rtlight = NULL;
5561 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5563 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5565 if (rsurface.mode != RSURFMODE_MULTIPASS)
5566 rsurface.mode = RSURFMODE_MULTIPASS;
5567 if (r_depthfirst.integer == 3)
5569 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5570 if (!r_view.showdebug)
5571 GL_Color(0, 0, 0, 1);
5573 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5577 GL_ColorMask(0,0,0,0);
5580 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5581 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5582 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5584 GL_BlendFunc(GL_ONE, GL_ZERO);
5586 GL_AlphaTest(false);
5587 R_Mesh_ColorPointer(NULL, 0, 0);
5588 R_Mesh_ResetTextureState();
5589 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5590 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5591 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5592 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5594 else if (r_depthfirst.integer == 3)
5596 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5598 GL_Color(0, 0, 0, 1);
5599 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5601 else if (r_showsurfaces.integer)
5603 if (rsurface.mode != RSURFMODE_MULTIPASS)
5604 rsurface.mode = RSURFMODE_MULTIPASS;
5605 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5606 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5608 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5609 GL_BlendFunc(GL_ONE, GL_ZERO);
5610 GL_DepthMask(writedepth);
5612 GL_AlphaTest(false);
5613 R_Mesh_ColorPointer(NULL, 0, 0);
5614 R_Mesh_ResetTextureState();
5615 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5616 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5617 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5619 else if (gl_lightmaps.integer)
5622 if (rsurface.mode != RSURFMODE_MULTIPASS)
5623 rsurface.mode = RSURFMODE_MULTIPASS;
5624 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5626 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5627 GL_BlendFunc(GL_ONE, GL_ZERO);
5628 GL_DepthMask(writedepth);
5630 GL_AlphaTest(false);
5631 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5632 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5633 R_Mesh_ColorPointer(NULL, 0, 0);
5634 memset(&m, 0, sizeof(m));
5635 m.tex[0] = R_GetTexture(r_texture_white);
5636 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5637 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5638 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5639 R_Mesh_TextureState(&m);
5640 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5641 if (rsurface.lightmode == 2)
5642 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5643 else if (rsurface.uselightmaptexture)
5644 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5646 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5647 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5649 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5651 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5652 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5654 else if (rsurface.texture->currentnumlayers)
5656 // write depth for anything we skipped on the depth-only pass earlier
5657 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5659 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5660 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5661 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5662 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5663 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5665 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5666 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5667 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5668 if (r_glsl.integer && gl_support_fragment_shader)
5669 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5670 else if (gl_combine.integer && r_textureunits.integer >= 2)
5671 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5673 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5674 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5677 GL_LockArrays(0, 0);
5680 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5683 int texturenumsurfaces, endsurface;
5685 msurface_t *surface;
5686 msurface_t *texturesurfacelist[1024];
5688 // if the model is static it doesn't matter what value we give for
5689 // wantnormals and wanttangents, so this logic uses only rules applicable
5690 // to a model, knowing that they are meaningless otherwise
5691 if (ent == r_refdef.worldentity)
5692 RSurf_ActiveWorldEntity();
5693 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5694 RSurf_ActiveModelEntity(ent, false, false);
5696 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5698 for (i = 0;i < numsurfaces;i = j)
5701 surface = rsurface.modelsurfaces + surfacelist[i];
5702 texture = surface->texture;
5703 R_UpdateTextureInfo(ent, texture);
5704 rsurface.texture = texture->currentframe;
5705 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5706 // scan ahead until we find a different texture
5707 endsurface = min(i + 1024, numsurfaces);
5708 texturenumsurfaces = 0;
5709 texturesurfacelist[texturenumsurfaces++] = surface;
5710 for (;j < endsurface;j++)
5712 surface = rsurface.modelsurfaces + surfacelist[j];
5713 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5715 texturesurfacelist[texturenumsurfaces++] = surface;
5717 // render the range of surfaces
5718 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5724 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5727 vec3_t tempcenter, center;
5729 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5732 for (i = 0;i < numsurfaces;i++)
5733 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5734 R_Water_AddWaterPlane(surfacelist[i]);
5737 // break the surface list down into batches by texture and use of lightmapping
5738 for (i = 0;i < numsurfaces;i = j)
5741 // texture is the base texture pointer, rsurface.texture is the
5742 // current frame/skin the texture is directing us to use (for example
5743 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5744 // use skin 1 instead)
5745 texture = surfacelist[i]->texture;
5746 rsurface.texture = texture->currentframe;
5747 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5748 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5750 // if this texture is not the kind we want, skip ahead to the next one
5751 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5755 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5757 // transparent surfaces get pushed off into the transparent queue
5758 const msurface_t *surface = surfacelist[i];
5761 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5762 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5763 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5764 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5765 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5769 // simply scan ahead until we find a different texture or lightmap state
5770 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5772 // render the range of surfaces
5773 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5778 float locboxvertex3f[6*4*3] =
5780 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5781 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5782 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5783 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5784 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5785 1,0,0, 0,0,0, 0,1,0, 1,1,0
5788 int locboxelement3i[6*2*3] =
5798 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5801 cl_locnode_t *loc = (cl_locnode_t *)ent;
5803 float vertex3f[6*4*3];
5805 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5806 GL_DepthMask(false);
5807 GL_DepthRange(0, 1);
5808 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5810 GL_CullFace(GL_NONE);
5811 R_Mesh_Matrix(&identitymatrix);
5813 R_Mesh_VertexPointer(vertex3f, 0, 0);
5814 R_Mesh_ColorPointer(NULL, 0, 0);
5815 R_Mesh_ResetTextureState();
5818 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5819 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5820 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5821 surfacelist[0] < 0 ? 0.5f : 0.125f);
5823 if (VectorCompare(loc->mins, loc->maxs))
5825 VectorSet(size, 2, 2, 2);
5826 VectorMA(loc->mins, -0.5f, size, mins);
5830 VectorCopy(loc->mins, mins);
5831 VectorSubtract(loc->maxs, loc->mins, size);
5834 for (i = 0;i < 6*4*3;)
5835 for (j = 0;j < 3;j++, i++)
5836 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5838 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5841 void R_DrawLocs(void)
5844 cl_locnode_t *loc, *nearestloc;
5846 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5847 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5849 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5850 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5854 void R_DrawDebugModel(entity_render_t *ent)
5856 int i, j, k, l, flagsmask;
5857 const int *elements;
5859 msurface_t *surface;
5860 model_t *model = ent->model;
5863 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
5865 R_Mesh_ColorPointer(NULL, 0, 0);
5866 R_Mesh_ResetTextureState();
5867 GL_DepthRange(0, 1);
5868 GL_DepthTest(!r_showdisabledepthtest.integer);
5869 GL_DepthMask(false);
5870 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5872 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
5874 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5875 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5877 if (brush->colbrushf && brush->colbrushf->numtriangles)
5879 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
5880 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
5881 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
5884 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5886 if (surface->num_collisiontriangles)
5888 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
5889 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
5890 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
5895 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5897 if (r_showtris.integer || r_shownormals.integer)
5899 if (r_showdisabledepthtest.integer)
5901 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5902 GL_DepthMask(false);
5906 GL_BlendFunc(GL_ONE, GL_ZERO);
5909 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5911 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5913 rsurface.texture = surface->texture->currentframe;
5914 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5916 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5917 if (r_showtris.value > 0)
5919 if (!rsurface.texture->currentlayers->depthmask)
5920 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
5921 else if (ent == r_refdef.worldentity)
5922 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
5924 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
5925 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5928 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5930 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5931 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5932 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5933 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5938 if (r_shownormals.value > 0)
5940 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
5942 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5944 VectorCopy(rsurface.vertex3f + l * 3, v);
5945 qglVertex3f(v[0], v[1], v[2]);
5946 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5947 qglVertex3f(v[0], v[1], v[2]);
5951 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
5953 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5955 VectorCopy(rsurface.vertex3f + l * 3, v);
5956 qglVertex3f(v[0], v[1], v[2]);
5957 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5958 qglVertex3f(v[0], v[1], v[2]);
5962 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
5964 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5966 VectorCopy(rsurface.vertex3f + l * 3, v);
5967 qglVertex3f(v[0], v[1], v[2]);
5968 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5969 qglVertex3f(v[0], v[1], v[2]);
5976 rsurface.texture = NULL;
5980 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5981 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
5983 int i, j, endj, f, flagsmask;
5984 int counttriangles = 0;
5985 msurface_t *surface, **surfacechain;
5987 model_t *model = r_refdef.worldmodel;
5988 const int maxsurfacelist = 1024;
5989 int numsurfacelist = 0;
5990 msurface_t *surfacelist[1024];
5994 RSurf_ActiveWorldEntity();
5996 // update light styles
5997 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5999 for (i = 0;i < model->brushq1.light_styles;i++)
6001 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6003 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6004 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6005 for (;(surface = *surfacechain);surfacechain++)
6006 surface->cached_dlight = true;
6011 R_UpdateAllTextureInfo(r_refdef.worldentity);
6012 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6016 R_DrawDebugModel(r_refdef.worldentity);
6022 rsurface.uselightmaptexture = false;
6023 rsurface.texture = NULL;
6025 j = model->firstmodelsurface;
6026 endj = j + model->nummodelsurfaces;
6029 // quickly skip over non-visible surfaces
6030 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6032 // quickly iterate over visible surfaces
6033 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6035 // process this surface
6036 surface = model->data_surfaces + j;
6037 // if this surface fits the criteria, add it to the list
6038 if (surface->num_triangles)
6040 // if lightmap parameters changed, rebuild lightmap texture
6041 if (surface->cached_dlight)
6042 R_BuildLightMap(r_refdef.worldentity, surface);
6043 // add face to draw list
6044 surfacelist[numsurfacelist++] = surface;
6045 counttriangles += surface->num_triangles;
6046 if (numsurfacelist >= maxsurfacelist)
6048 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6055 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6056 r_refdef.stats.entities_triangles += counttriangles;
6060 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6062 int i, f, flagsmask;
6063 int counttriangles = 0;
6064 msurface_t *surface, *endsurface, **surfacechain;
6066 model_t *model = ent->model;
6067 const int maxsurfacelist = 1024;
6068 int numsurfacelist = 0;
6069 msurface_t *surfacelist[1024];
6073 // if the model is static it doesn't matter what value we give for
6074 // wantnormals and wanttangents, so this logic uses only rules applicable
6075 // to a model, knowing that they are meaningless otherwise
6076 if (ent == r_refdef.worldentity)
6077 RSurf_ActiveWorldEntity();
6078 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6079 RSurf_ActiveModelEntity(ent, false, false);
6081 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6083 // update light styles
6084 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6086 for (i = 0;i < model->brushq1.light_styles;i++)
6088 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6090 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6091 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6092 for (;(surface = *surfacechain);surfacechain++)
6093 surface->cached_dlight = true;
6098 R_UpdateAllTextureInfo(ent);
6099 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6103 R_DrawDebugModel(ent);
6109 rsurface.uselightmaptexture = false;
6110 rsurface.texture = NULL;
6112 surface = model->data_surfaces + model->firstmodelsurface;
6113 endsurface = surface + model->nummodelsurfaces;
6114 for (;surface < endsurface;surface++)
6116 // if this surface fits the criteria, add it to the list
6117 if (surface->num_triangles)
6119 // if lightmap parameters changed, rebuild lightmap texture
6120 if (surface->cached_dlight)
6121 R_BuildLightMap(ent, surface);
6122 // add face to draw list
6123 surfacelist[numsurfacelist++] = surface;
6124 counttriangles += surface->num_triangles;
6125 if (numsurfacelist >= maxsurfacelist)
6127 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6133 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6134 r_refdef.stats.entities_triangles += counttriangles;