2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
85 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
86 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
87 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
88 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
90 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
91 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
92 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
94 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
95 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
96 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
97 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
98 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
99 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
100 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
102 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
103 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
104 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
105 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
107 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
109 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
114 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
115 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
116 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
117 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
118 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
120 extern qboolean v_flipped_state;
122 typedef struct r_glsl_bloomshader_s
125 int loc_Texture_Bloom;
127 r_glsl_bloomshader_t;
129 static struct r_bloomstate_s
134 int bloomwidth, bloomheight;
136 int screentexturewidth, screentextureheight;
137 rtexture_t *texture_screen;
139 int bloomtexturewidth, bloomtextureheight;
140 rtexture_t *texture_bloom;
142 r_glsl_bloomshader_t *shader;
144 // arrays for rendering the screen passes
145 float screentexcoord2f[8];
146 float bloomtexcoord2f[8];
147 float offsettexcoord2f[8];
151 typedef struct r_waterstate_waterplane_s
153 rtexture_t *texture_refraction;
154 rtexture_t *texture_reflection;
156 int materialflags; // combined flags of all water surfaces on this plane
157 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
160 r_waterstate_waterplane_t;
162 #define MAX_WATERPLANES 16
164 static struct r_waterstate_s
168 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
170 int waterwidth, waterheight;
171 int texturewidth, textureheight;
173 int maxwaterplanes; // same as MAX_WATERPLANES
175 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
177 float screenscale[2];
178 float screencenter[2];
182 // shadow volume bsp struct with automatically growing nodes buffer
185 rtexture_t *r_texture_blanknormalmap;
186 rtexture_t *r_texture_white;
187 rtexture_t *r_texture_grey128;
188 rtexture_t *r_texture_black;
189 rtexture_t *r_texture_notexture;
190 rtexture_t *r_texture_whitecube;
191 rtexture_t *r_texture_normalizationcube;
192 rtexture_t *r_texture_fogattenuation;
193 //rtexture_t *r_texture_fogintensity;
195 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
196 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
198 // vertex coordinates for a quad that covers the screen exactly
199 const static float r_screenvertex3f[12] =
207 extern void R_DrawModelShadows(void);
209 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
212 for (i = 0;i < verts;i++)
223 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
226 for (i = 0;i < verts;i++)
236 // FIXME: move this to client?
239 if (gamemode == GAME_NEHAHRA)
241 Cvar_Set("gl_fogenable", "0");
242 Cvar_Set("gl_fogdensity", "0.2");
243 Cvar_Set("gl_fogred", "0.3");
244 Cvar_Set("gl_foggreen", "0.3");
245 Cvar_Set("gl_fogblue", "0.3");
247 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
250 float FogPoint_World(const vec3_t p)
252 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
253 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
256 float FogPoint_Model(const vec3_t p)
258 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
259 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
262 static void R_BuildBlankTextures(void)
264 unsigned char data[4];
265 data[0] = 128; // normal X
266 data[1] = 128; // normal Y
267 data[2] = 255; // normal Z
268 data[3] = 128; // height
269 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
274 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
279 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
287 static void R_BuildNoTexture(void)
290 unsigned char pix[16][16][4];
291 // this makes a light grey/dark grey checkerboard texture
292 for (y = 0;y < 16;y++)
294 for (x = 0;x < 16;x++)
296 if ((y < 8) ^ (x < 8))
312 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
315 static void R_BuildWhiteCube(void)
317 unsigned char data[6*1*1*4];
318 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
319 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
320 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
321 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
322 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
323 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
324 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
327 static void R_BuildNormalizationCube(void)
331 vec_t s, t, intensity;
333 unsigned char data[6][NORMSIZE][NORMSIZE][4];
334 for (side = 0;side < 6;side++)
336 for (y = 0;y < NORMSIZE;y++)
338 for (x = 0;x < NORMSIZE;x++)
340 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
376 intensity = 127.0f / sqrt(DotProduct(v, v));
377 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
378 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
379 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
380 data[side][y][x][3] = 255;
384 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
387 static void R_BuildFogTexture(void)
391 unsigned char data1[FOGWIDTH][4];
392 //unsigned char data2[FOGWIDTH][4];
393 for (x = 0;x < FOGWIDTH;x++)
395 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
400 //data2[x][0] = 255 - b;
401 //data2[x][1] = 255 - b;
402 //data2[x][2] = 255 - b;
405 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
406 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 static const char *builtinshaderstring =
410 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
411 "// written by Forest 'LordHavoc' Hale\n"
413 "// common definitions between vertex shader and fragment shader:\n"
415 "#ifdef __GLSL_CG_DATA_TYPES\n"
416 "# define myhalf half\n"
417 "# define myhvec2 hvec2\n"
418 "# define myhvec3 hvec3\n"
419 "# define myhvec4 hvec4\n"
421 "# define myhalf float\n"
422 "# define myhvec2 vec2\n"
423 "# define myhvec3 vec3\n"
424 "# define myhvec4 vec4\n"
427 "varying vec2 TexCoord;\n"
428 "varying vec2 TexCoordLightmap;\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 CubeVector;\n"
434 "//#ifdef MODE_LIGHTSOURCE\n"
435 "varying vec3 LightVector;\n"
437 "//# ifdef MODE_LIGHTDIRECTION\n"
438 "//varying vec3 LightVector;\n"
442 "varying vec3 EyeVector;\n"
444 "varying vec3 EyeVectorModelSpace;\n"
447 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
448 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
449 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
451 "//#ifdef MODE_WATER\n"
452 "varying vec4 ModelViewProjectionPosition;\n"
454 "//# ifdef MODE_REFRACTION\n"
455 "//varying vec4 ModelViewProjectionPosition;\n"
457 "//# ifdef USEREFLECTION\n"
458 "//varying vec4 ModelViewProjectionPosition;\n"
467 "// vertex shader specific:\n"
468 "#ifdef VERTEX_SHADER\n"
470 "uniform vec3 LightPosition;\n"
471 "uniform vec3 EyePosition;\n"
472 "uniform vec3 LightDir;\n"
474 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
478 " gl_FrontColor = gl_Color;\n"
479 " // copy the surface texcoord\n"
480 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
481 "#ifndef MODE_LIGHTSOURCE\n"
482 "# ifndef MODE_LIGHTDIRECTION\n"
483 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
487 "#ifdef MODE_LIGHTSOURCE\n"
488 " // transform vertex position into light attenuation/cubemap space\n"
489 " // (-1 to +1 across the light box)\n"
490 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
492 " // transform unnormalized light direction into tangent space\n"
493 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
494 " // normalize it per pixel)\n"
495 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
496 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
497 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
498 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
501 "#ifdef MODE_LIGHTDIRECTION\n"
502 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
503 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
504 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
507 " // transform unnormalized eye direction into tangent space\n"
509 " vec3 EyeVectorModelSpace;\n"
511 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
512 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
513 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
514 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
516 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
517 " VectorS = gl_MultiTexCoord1.xyz;\n"
518 " VectorT = gl_MultiTexCoord2.xyz;\n"
519 " VectorR = gl_MultiTexCoord3.xyz;\n"
522 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
523 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
524 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
525 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
528 "// transform vertex to camera space, using ftransform to match non-VS\n"
530 " gl_Position = ftransform();\n"
532 "#ifdef MODE_WATER\n"
533 " ModelViewProjectionPosition = gl_Position;\n"
535 "#ifdef MODE_REFRACTION\n"
536 " ModelViewProjectionPosition = gl_Position;\n"
538 "#ifdef USEREFLECTION\n"
539 " 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 MODE_WATER\n"
575 "uniform vec4 DistortScaleRefractReflect;\n"
576 "uniform vec4 ScreenScaleRefractReflect;\n"
577 "uniform vec4 ScreenCenterRefractReflect;\n"
578 "uniform myhvec4 RefractColor;\n"
579 "uniform myhvec4 ReflectColor;\n"
580 "uniform myhalf ReflectFactor;\n"
581 "uniform myhalf ReflectOffset;\n"
583 "//# ifdef MODE_REFRACTION\n"
584 "//uniform vec4 DistortScaleRefractReflect;\n"
585 "//uniform vec4 ScreenScaleRefractReflect;\n"
586 "//uniform vec4 ScreenCenterRefractReflect;\n"
587 "//uniform myhvec4 RefractColor;\n"
588 "//# ifdef USEREFLECTION\n"
589 "//uniform myhvec4 ReflectColor;\n"
592 "//# ifdef USEREFLECTION\n"
593 "//uniform vec4 DistortScaleRefractReflect;\n"
594 "//uniform vec4 ScreenScaleRefractReflect;\n"
595 "//uniform vec4 ScreenCenterRefractReflect;\n"
596 "//uniform myhvec4 ReflectColor;\n"
601 "uniform myhalf GlowScale;\n"
602 "uniform myhalf SceneBrightness;\n"
603 "#ifdef USECONTRASTBOOST\n"
604 "uniform myhalf ContrastBoostCoeff;\n"
607 "uniform float OffsetMapping_Scale;\n"
608 "uniform float OffsetMapping_Bias;\n"
609 "uniform float FogRangeRecip;\n"
611 "uniform myhalf AmbientScale;\n"
612 "uniform myhalf DiffuseScale;\n"
613 "uniform myhalf SpecularScale;\n"
614 "uniform myhalf SpecularPower;\n"
616 "#ifdef USEOFFSETMAPPING\n"
617 "vec2 OffsetMapping(vec2 TexCoord)\n"
619 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
620 " // 14 sample relief mapping: linear search and then binary search\n"
621 " // this basically steps forward a small amount repeatedly until it finds\n"
622 " // itself inside solid, then jitters forward and back using decreasing\n"
623 " // amounts to find the impact\n"
624 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
625 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
626 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
627 " vec3 RT = vec3(TexCoord, 1);\n"
628 " OffsetVector *= 0.1;\n"
629 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
630 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
631 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
632 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
633 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
634 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
635 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
636 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
637 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
638 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
639 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
640 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
641 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
642 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
645 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
646 " // this basically moves forward the full distance, and then backs up based\n"
647 " // on height of samples\n"
648 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
649 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
650 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
651 " TexCoord += OffsetVector;\n"
652 " OffsetVector *= 0.333;\n"
653 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
654 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
655 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
656 " return TexCoord;\n"
659 "#endif // USEOFFSETMAPPING\n"
661 "#ifdef MODE_WATER\n"
666 "#ifdef USEOFFSETMAPPING\n"
667 " // apply offsetmapping\n"
668 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
669 "#define TexCoord TexCoordOffset\n"
672 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
673 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
674 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
675 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
676 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
679 "#else // MODE_WATER\n"
680 "#ifdef MODE_REFRACTION\n"
682 "// refraction pass\n"
685 "#ifdef USEOFFSETMAPPING\n"
686 " // apply offsetmapping\n"
687 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
688 "#define TexCoord TexCoordOffset\n"
691 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
692 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
693 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
694 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
697 "#else // MODE_REFRACTION\n"
700 "#ifdef USEOFFSETMAPPING\n"
701 " // apply offsetmapping\n"
702 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
703 "#define TexCoord TexCoordOffset\n"
706 " // combine the diffuse textures (base, pants, shirt)\n"
707 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
708 "#ifdef USECOLORMAPPING\n"
709 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
715 "#ifdef MODE_LIGHTSOURCE\n"
718 " // calculate surface normal, light normal, and specular normal\n"
719 " // compute color intensity for the two textures (colormap and glossmap)\n"
720 " // scale by light color and attenuation as efficiently as possible\n"
721 " // (do as much scalar math as possible rather than vector math)\n"
722 "# ifdef USESPECULAR\n"
723 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
724 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
725 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
727 " // calculate directional shading\n"
728 " 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"
730 "# ifdef USEDIFFUSE\n"
731 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
732 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
734 " // calculate directional shading\n"
735 " 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"
737 " // calculate directionless shading\n"
738 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
742 "# ifdef USECUBEFILTER\n"
743 " // apply light cubemap filter\n"
744 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
745 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
747 " color *= myhvec4(gl_Color);\n"
748 "#endif // MODE_LIGHTSOURCE\n"
753 "#ifdef MODE_LIGHTDIRECTION\n"
754 " // directional model lighting\n"
756 " // get the surface normal and light normal\n"
757 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
758 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
760 " // calculate directional shading\n"
761 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
762 "# ifdef USESPECULAR\n"
763 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
764 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
766 " color *= myhvec4(gl_Color);\n"
767 "#endif // MODE_LIGHTDIRECTION\n"
772 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
773 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
775 " // get the surface normal and light normal\n"
776 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
778 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
779 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
780 " // calculate directional shading\n"
781 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
782 "# ifdef USESPECULAR\n"
783 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
784 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
787 " // apply lightmap color\n"
788 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
789 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
794 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
795 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
797 " // get the surface normal and light normal\n"
798 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
800 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
801 " // calculate directional shading\n"
802 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
803 "# ifdef USESPECULAR\n"
804 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
805 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
808 " // apply lightmap color\n"
809 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
810 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
815 "#ifdef MODE_LIGHTMAP\n"
816 " // apply lightmap color\n"
817 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
818 "#endif // MODE_LIGHTMAP\n"
828 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
831 "#ifdef USECONTRASTBOOST\n"
832 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
835 " color.rgb *= SceneBrightness;\n"
837 "#ifndef MODE_LIGHTSOURCE\n"
838 "# ifdef USEREFLECTION\n"
839 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
840 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
841 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
842 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
848 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
851 " gl_FragColor = vec4(color);\n"
853 "#endif // MODE_REFRACTION\n"
854 "#endif // MODE_WATER\n"
856 "#endif // FRAGMENT_SHADER\n"
859 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
860 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
861 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
862 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
863 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
864 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
865 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
866 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
867 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
868 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
869 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
871 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
872 const char *shaderpermutationinfo[][2] =
874 {"#define USECOLORMAPPING\n", " colormapping"},
875 {"#define USECONTRASTBOOST\n", " contrastboost"},
876 {"#define USEFOG\n", " fog"},
877 {"#define USECUBEFILTER\n", " cubefilter"},
878 {"#define USEGLOW\n", " glow"},
879 {"#define USEDIFFUSE\n", " diffuse"},
880 {"#define USESPECULAR\n", " specular"},
881 {"#define USEREFLECTION\n", " reflection"},
882 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
883 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
887 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
888 typedef enum shadermode_e
890 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
891 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
892 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
893 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
894 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
895 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
896 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
901 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
902 const char *shadermodeinfo[][2] =
904 {"#define MODE_LIGHTMAP\n", " lightmap"},
905 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
906 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
907 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
908 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
909 {"#define MODE_REFRACTION\n", " refraction"},
910 {"#define MODE_WATER\n", " water"},
914 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
916 typedef struct r_glsl_permutation_s
918 // indicates if we have tried compiling this permutation already
920 // 0 if compilation failed
922 // locations of detected uniforms in program object, or -1 if not found
923 int loc_Texture_Normal;
924 int loc_Texture_Color;
925 int loc_Texture_Gloss;
926 int loc_Texture_Cube;
927 int loc_Texture_Attenuation;
928 int loc_Texture_FogMask;
929 int loc_Texture_Pants;
930 int loc_Texture_Shirt;
931 int loc_Texture_Lightmap;
932 int loc_Texture_Deluxemap;
933 int loc_Texture_Glow;
934 int loc_Texture_Refraction;
935 int loc_Texture_Reflection;
937 int loc_LightPosition;
942 int loc_FogRangeRecip;
943 int loc_AmbientScale;
944 int loc_DiffuseScale;
945 int loc_SpecularScale;
946 int loc_SpecularPower;
948 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
949 int loc_OffsetMapping_Scale;
950 int loc_AmbientColor;
951 int loc_DiffuseColor;
952 int loc_SpecularColor;
954 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
955 int loc_DistortScaleRefractReflect;
956 int loc_ScreenScaleRefractReflect;
957 int loc_ScreenCenterRefractReflect;
958 int loc_RefractColor;
959 int loc_ReflectColor;
960 int loc_ReflectFactor;
961 int loc_ReflectOffset;
963 r_glsl_permutation_t;
965 // information about each possible shader permutation
966 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
967 // currently selected permutation
968 r_glsl_permutation_t *r_glsl_permutation;
970 // these are additional flags used only by R_GLSL_CompilePermutation
971 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
972 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
973 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
975 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
978 qboolean shaderfound;
979 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
980 int vertstrings_count;
981 int geomstrings_count;
982 int fragstrings_count;
984 const char *vertstrings_list[32+1];
985 const char *geomstrings_list[32+1];
986 const char *fragstrings_list[32+1];
987 char permutationname[256];
992 vertstrings_list[0] = "#define VERTEX_SHADER\n";
993 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
994 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
995 vertstrings_count = 1;
996 geomstrings_count = 1;
997 fragstrings_count = 1;
998 permutationname[0] = 0;
999 i = permutation / SHADERPERMUTATION_MODEBASE;
1000 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1001 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1002 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1003 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1004 for (i = 0;shaderpermutationinfo[i][0];i++)
1006 if (permutation & (1<<i))
1008 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1009 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1010 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1011 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1015 // keep line numbers correct
1016 vertstrings_list[vertstrings_count++] = "\n";
1017 geomstrings_list[geomstrings_count++] = "\n";
1018 fragstrings_list[fragstrings_count++] = "\n";
1021 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1022 shaderfound = false;
1025 Con_DPrint("from disk... ");
1026 vertstrings_list[vertstrings_count++] = shaderstring;
1027 geomstrings_list[geomstrings_count++] = shaderstring;
1028 fragstrings_list[fragstrings_count++] = shaderstring;
1031 else if (!strcmp(filename, "glsl/default.glsl"))
1033 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1034 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1035 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1038 // clear any lists that are not needed by this shader
1039 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1040 vertstrings_count = 0;
1041 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1042 geomstrings_count = 0;
1043 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1044 fragstrings_count = 0;
1045 // compile the shader program
1046 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1047 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1051 qglUseProgramObjectARB(p->program);CHECKGLERROR
1052 // look up all the uniform variable names we care about, so we don't
1053 // have to look them up every time we set them
1054 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1055 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1056 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1057 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1058 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1059 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1060 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1061 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1062 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1063 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1064 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1065 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1066 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1067 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1068 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1069 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1070 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1071 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1072 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1073 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1074 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1075 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1076 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1077 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1078 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1079 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1080 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1081 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1082 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1083 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1084 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1085 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1086 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1087 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1088 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1089 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1090 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1091 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1092 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1093 // initialize the samplers to refer to the texture units we use
1094 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1095 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1096 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1097 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1098 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1099 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1100 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1101 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1102 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1103 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1104 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1105 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1106 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1108 qglUseProgramObjectARB(0);CHECKGLERROR
1109 if (developer.integer)
1110 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1114 if (developer.integer)
1115 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1117 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1120 Mem_Free(shaderstring);
1123 void R_GLSL_Restart_f(void)
1126 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1127 if (r_glsl_permutations[i].program)
1128 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1129 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1132 void R_GLSL_DumpShader_f(void)
1136 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1139 Con_Printf("failed to write to glsl/default.glsl\n");
1143 FS_Print(file, "// The engine may define the following macros:\n");
1144 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1145 for (i = 0;shadermodeinfo[i][0];i++)
1146 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1147 for (i = 0;shaderpermutationinfo[i][0];i++)
1148 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1149 FS_Print(file, "\n");
1150 FS_Print(file, builtinshaderstring);
1153 Con_Printf("glsl/default.glsl written\n");
1156 extern rtexture_t *r_shadow_attenuationgradienttexture;
1157 extern rtexture_t *r_shadow_attenuation2dtexture;
1158 extern rtexture_t *r_shadow_attenuation3dtexture;
1159 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1161 // select a permutation of the lighting shader appropriate to this
1162 // combination of texture, entity, light source, and fogging, only use the
1163 // minimum features necessary to avoid wasting rendering time in the
1164 // fragment shader on features that are not being used
1165 const char *shaderfilename = NULL;
1166 unsigned int permutation = 0;
1167 unsigned int shadertype = 0;
1168 shadermode_t mode = 0;
1169 r_glsl_permutation = NULL;
1170 shaderfilename = "glsl/default.glsl";
1171 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1172 // TODO: implement geometry-shader based shadow volumes someday
1173 if (r_glsl_offsetmapping.integer)
1175 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1176 if (r_glsl_offsetmapping_reliefmapping.integer)
1177 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1179 if (rsurfacepass == RSURFPASS_BACKGROUND)
1181 // distorted background
1182 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1183 mode = SHADERMODE_WATER;
1185 mode = SHADERMODE_REFRACTION;
1187 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1190 mode = SHADERMODE_LIGHTSOURCE;
1191 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1192 permutation |= SHADERPERMUTATION_CUBEFILTER;
1193 if (diffusescale > 0)
1194 permutation |= SHADERPERMUTATION_DIFFUSE;
1195 if (specularscale > 0)
1196 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1197 if (r_refdef.fogenabled)
1198 permutation |= SHADERPERMUTATION_FOG;
1199 if (rsurface.texture->colormapping)
1200 permutation |= SHADERPERMUTATION_COLORMAPPING;
1201 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1202 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1203 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1204 permutation |= SHADERPERMUTATION_REFLECTION;
1206 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1208 // bright unshaded geometry
1209 mode = SHADERMODE_LIGHTMAP;
1210 if (rsurface.texture->currentskinframe->glow)
1211 permutation |= SHADERPERMUTATION_GLOW;
1212 if (r_refdef.fogenabled)
1213 permutation |= SHADERPERMUTATION_FOG;
1214 if (rsurface.texture->colormapping)
1215 permutation |= SHADERPERMUTATION_COLORMAPPING;
1216 if (r_glsl_offsetmapping.integer)
1218 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1219 if (r_glsl_offsetmapping_reliefmapping.integer)
1220 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1222 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1223 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1225 permutation |= SHADERPERMUTATION_REFLECTION;
1227 else if (modellighting)
1229 // directional model lighting
1230 mode = SHADERMODE_LIGHTDIRECTION;
1231 if (rsurface.texture->currentskinframe->glow)
1232 permutation |= SHADERPERMUTATION_GLOW;
1233 if (specularscale > 0)
1234 permutation |= SHADERPERMUTATION_SPECULAR;
1235 if (r_refdef.fogenabled)
1236 permutation |= SHADERPERMUTATION_FOG;
1237 if (rsurface.texture->colormapping)
1238 permutation |= SHADERPERMUTATION_COLORMAPPING;
1239 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1240 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1241 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1242 permutation |= SHADERPERMUTATION_REFLECTION;
1247 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1249 // deluxemapping (light direction texture)
1250 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1251 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1253 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1254 if (specularscale > 0)
1255 permutation |= SHADERPERMUTATION_SPECULAR;
1257 else if (r_glsl_deluxemapping.integer >= 2)
1259 // fake deluxemapping (uniform light direction in tangentspace)
1260 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1261 if (specularscale > 0)
1262 permutation |= SHADERPERMUTATION_SPECULAR;
1266 // ordinary lightmapping
1267 mode = SHADERMODE_LIGHTMAP;
1269 if (rsurface.texture->currentskinframe->glow)
1270 permutation |= SHADERPERMUTATION_GLOW;
1271 if (r_refdef.fogenabled)
1272 permutation |= SHADERPERMUTATION_FOG;
1273 if (rsurface.texture->colormapping)
1274 permutation |= SHADERPERMUTATION_COLORMAPPING;
1275 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1276 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1278 permutation |= SHADERPERMUTATION_REFLECTION;
1280 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1281 if (!r_glsl_permutations[permutation].program)
1283 if (!r_glsl_permutations[permutation].compiled)
1284 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1285 if (!r_glsl_permutations[permutation].program)
1287 // remove features until we find a valid permutation
1289 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1293 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");
1294 Cvar_SetValueQuick(&r_glsl, 0);
1295 return 0; // no bit left to clear
1297 // reduce i more quickly whenever it would not remove any bits
1298 if (!(permutation & i))
1301 if (!r_glsl_permutations[permutation].compiled)
1302 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1303 if (r_glsl_permutations[permutation].program)
1308 r_glsl_permutation = r_glsl_permutations + permutation;
1310 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1311 if (mode == SHADERMODE_LIGHTSOURCE)
1313 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1314 if (permutation & SHADERPERMUTATION_DIFFUSE)
1316 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1317 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1318 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1319 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1323 // ambient only is simpler
1324 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1325 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1326 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1327 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1330 else if (mode == SHADERMODE_LIGHTDIRECTION)
1332 if (r_glsl_permutation->loc_AmbientColor >= 0)
1333 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1334 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1335 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1336 if (r_glsl_permutation->loc_SpecularColor >= 0)
1337 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1338 if (r_glsl_permutation->loc_LightDir >= 0)
1339 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1343 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1344 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1345 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1347 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1348 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1350 // The formula used is actually:
1351 // color.rgb *= SceneBrightness;
1352 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1353 // I simplify that to
1354 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1355 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1357 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1358 // and do [[calculations]] here in the engine
1359 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1360 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1363 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1364 if (r_glsl_permutation->loc_FogColor >= 0)
1366 // additive passes are only darkened by fog, not tinted
1367 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1368 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1373 // color.rgb *= SceneBrightness;
1374 VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1375 if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1377 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1378 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1379 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1380 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1382 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1385 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1387 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1388 if (r_glsl_permutation->loc_Color_Pants >= 0)
1390 if (rsurface.texture->currentskinframe->pants)
1391 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1393 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1395 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1397 if (rsurface.texture->currentskinframe->shirt)
1398 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1400 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1402 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1403 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1404 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1405 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1406 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]);
1407 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]);
1408 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1409 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1410 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1411 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1416 #define SKINFRAME_HASH 1024
1420 int loadsequence; // incremented each level change
1421 memexpandablearray_t array;
1422 skinframe_t *hash[SKINFRAME_HASH];
1426 void R_SkinFrame_PrepareForPurge(void)
1428 r_skinframe.loadsequence++;
1429 // wrap it without hitting zero
1430 if (r_skinframe.loadsequence >= 200)
1431 r_skinframe.loadsequence = 1;
1434 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1438 // mark the skinframe as used for the purging code
1439 skinframe->loadsequence = r_skinframe.loadsequence;
1442 void R_SkinFrame_Purge(void)
1446 for (i = 0;i < SKINFRAME_HASH;i++)
1448 for (s = r_skinframe.hash[i];s;s = s->next)
1450 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1452 if (s->base == r_texture_notexture) s->base = NULL;
1453 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1454 if (s->merged == s->base) s->merged = NULL;
1455 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1456 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1457 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1458 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1459 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1460 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1461 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1462 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1463 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1464 s->loadsequence = 0;
1470 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1474 char basename[MAX_QPATH];
1476 Image_StripImageExtension(name, basename, sizeof(basename));
1478 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1479 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1480 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1486 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1487 memset(item, 0, sizeof(*item));
1488 strlcpy(item->basename, basename, sizeof(item->basename));
1489 item->textureflags = textureflags;
1490 item->comparewidth = comparewidth;
1491 item->compareheight = compareheight;
1492 item->comparecrc = comparecrc;
1493 item->next = r_skinframe.hash[hashindex];
1494 r_skinframe.hash[hashindex] = item;
1496 R_SkinFrame_MarkUsed(item);
1500 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1502 // FIXME: it should be possible to disable loading various layers using
1503 // cvars, to prevent wasted loading time and memory usage if the user does
1505 qboolean loadnormalmap = true;
1506 qboolean loadgloss = true;
1507 qboolean loadpantsandshirt = true;
1508 qboolean loadglow = true;
1510 unsigned char *pixels;
1511 unsigned char *bumppixels;
1512 unsigned char *basepixels = NULL;
1513 int basepixels_width;
1514 int basepixels_height;
1515 skinframe_t *skinframe;
1517 if (cls.state == ca_dedicated)
1520 // return an existing skinframe if already loaded
1521 // if loading of the first image fails, don't make a new skinframe as it
1522 // would cause all future lookups of this to be missing
1523 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1524 if (skinframe && skinframe->base)
1527 basepixels = loadimagepixels(name, complain, 0, 0, true);
1528 if (basepixels == NULL)
1531 // we've got some pixels to store, so really allocate this new texture now
1533 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1534 skinframe->stain = NULL;
1535 skinframe->merged = NULL;
1536 skinframe->base = r_texture_notexture;
1537 skinframe->pants = NULL;
1538 skinframe->shirt = NULL;
1539 skinframe->nmap = r_texture_blanknormalmap;
1540 skinframe->gloss = NULL;
1541 skinframe->glow = NULL;
1542 skinframe->fog = NULL;
1544 basepixels_width = image_width;
1545 basepixels_height = image_height;
1546 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);
1548 if (textureflags & TEXF_ALPHA)
1550 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1551 if (basepixels[j] < 255)
1553 if (j < basepixels_width * basepixels_height * 4)
1555 // has transparent pixels
1556 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1557 for (j = 0;j < image_width * image_height * 4;j += 4)
1562 pixels[j+3] = basepixels[j+3];
1564 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);
1569 // _norm is the name used by tenebrae and has been adopted as standard
1572 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0, false)) != NULL)
1574 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);
1578 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0, false)) != NULL)
1580 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1581 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1582 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);
1584 Mem_Free(bumppixels);
1586 else if (r_shadow_bumpscale_basetexture.value > 0)
1588 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1589 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1590 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);
1594 // _luma is supported for tenebrae compatibility
1595 // (I think it's a very stupid name, but oh well)
1596 // _glow is the preferred name
1597 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0, false)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0, false)) != 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;}
1598 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0, false)) != 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;}
1599 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0, false)) != 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;}
1600 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0, false)) != 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;}
1603 Mem_Free(basepixels);
1608 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)
1613 for (i = 0;i < width*height;i++)
1614 if (((unsigned char *)&palette[in[i]])[3] > 0)
1616 if (i == width*height)
1619 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1622 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)
1625 unsigned char *temp1, *temp2;
1626 skinframe_t *skinframe;
1628 if (cls.state == ca_dedicated)
1631 // if already loaded just return it, otherwise make a new skinframe
1632 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1633 if (skinframe && skinframe->base)
1636 skinframe->stain = NULL;
1637 skinframe->merged = NULL;
1638 skinframe->base = r_texture_notexture;
1639 skinframe->pants = NULL;
1640 skinframe->shirt = NULL;
1641 skinframe->nmap = r_texture_blanknormalmap;
1642 skinframe->gloss = NULL;
1643 skinframe->glow = NULL;
1644 skinframe->fog = NULL;
1646 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1650 if (bitsperpixel == 32)
1652 if (r_shadow_bumpscale_basetexture.value > 0)
1654 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1655 temp2 = temp1 + width * height * 4;
1656 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1657 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1660 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1661 if (textureflags & TEXF_ALPHA)
1663 for (i = 3;i < width * height * 4;i += 4)
1664 if (skindata[i] < 255)
1666 if (i < width * height * 4)
1668 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1669 memcpy(fogpixels, skindata, width * height * 4);
1670 for (i = 0;i < width * height * 4;i += 4)
1671 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1672 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1673 Mem_Free(fogpixels);
1677 else if (bitsperpixel == 8)
1679 if (r_shadow_bumpscale_basetexture.value > 0)
1681 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1682 temp2 = temp1 + width * height * 4;
1683 if (bitsperpixel == 32)
1684 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1687 // use either a custom palette or the quake palette
1688 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1689 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1691 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1694 // use either a custom palette, or the quake palette
1695 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
1696 if (!palette && loadglowtexture)
1697 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1698 if (!palette && loadpantsandshirt)
1700 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1701 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1703 if (skinframe->pants || skinframe->shirt)
1704 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1705 if (textureflags & TEXF_ALPHA)
1707 // if not using a custom alphapalette, use the quake one
1709 alphapalette = palette_alpha;
1710 for (i = 0;i < width * height;i++)
1711 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1713 if (i < width * height)
1714 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1721 skinframe_t *R_SkinFrame_LoadMissing(void)
1723 skinframe_t *skinframe;
1725 if (cls.state == ca_dedicated)
1728 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1729 skinframe->stain = NULL;
1730 skinframe->merged = NULL;
1731 skinframe->base = r_texture_notexture;
1732 skinframe->pants = NULL;
1733 skinframe->shirt = NULL;
1734 skinframe->nmap = r_texture_blanknormalmap;
1735 skinframe->gloss = NULL;
1736 skinframe->glow = NULL;
1737 skinframe->fog = NULL;
1742 void gl_main_start(void)
1747 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1748 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1750 alpha = 1 - exp(r / ((double)x*(double)x));
1751 if (x == FOGMASKTABLEWIDTH - 1)
1753 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1756 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1757 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1759 // set up r_skinframe loading system for textures
1760 memset(&r_skinframe, 0, sizeof(r_skinframe));
1761 r_skinframe.loadsequence = 1;
1762 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1764 r_main_texturepool = R_AllocTexturePool();
1765 R_BuildBlankTextures();
1767 if (gl_texturecubemap)
1770 R_BuildNormalizationCube();
1772 R_BuildFogTexture();
1773 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1774 memset(&r_waterstate, 0, sizeof(r_waterstate));
1775 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1776 memset(&r_svbsp, 0, sizeof (r_svbsp));
1779 void gl_main_shutdown(void)
1781 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1782 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1784 // clear out the r_skinframe state
1785 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1786 memset(&r_skinframe, 0, sizeof(r_skinframe));
1789 Mem_Free(r_svbsp.nodes);
1790 memset(&r_svbsp, 0, sizeof (r_svbsp));
1791 R_FreeTexturePool(&r_main_texturepool);
1792 r_texture_blanknormalmap = NULL;
1793 r_texture_white = NULL;
1794 r_texture_grey128 = NULL;
1795 r_texture_black = NULL;
1796 r_texture_whitecube = NULL;
1797 r_texture_normalizationcube = NULL;
1798 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1799 memset(&r_waterstate, 0, sizeof(r_waterstate));
1803 extern void CL_ParseEntityLump(char *entitystring);
1804 void gl_main_newmap(void)
1806 // FIXME: move this code to client
1808 char *entities, entname[MAX_QPATH];
1811 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1812 l = (int)strlen(entname) - 4;
1813 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1815 memcpy(entname + l, ".ent", 5);
1816 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1818 CL_ParseEntityLump(entities);
1823 if (cl.worldmodel->brush.entities)
1824 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1828 void GL_Main_Init(void)
1830 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1832 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1833 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1834 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1835 if (gamemode == GAME_NEHAHRA)
1837 Cvar_RegisterVariable (&gl_fogenable);
1838 Cvar_RegisterVariable (&gl_fogdensity);
1839 Cvar_RegisterVariable (&gl_fogred);
1840 Cvar_RegisterVariable (&gl_foggreen);
1841 Cvar_RegisterVariable (&gl_fogblue);
1842 Cvar_RegisterVariable (&gl_fogstart);
1843 Cvar_RegisterVariable (&gl_fogend);
1845 Cvar_RegisterVariable(&r_depthfirst);
1846 Cvar_RegisterVariable(&r_nearclip);
1847 Cvar_RegisterVariable(&r_showbboxes);
1848 Cvar_RegisterVariable(&r_showsurfaces);
1849 Cvar_RegisterVariable(&r_showtris);
1850 Cvar_RegisterVariable(&r_shownormals);
1851 Cvar_RegisterVariable(&r_showlighting);
1852 Cvar_RegisterVariable(&r_showshadowvolumes);
1853 Cvar_RegisterVariable(&r_showcollisionbrushes);
1854 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1855 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1856 Cvar_RegisterVariable(&r_showdisabledepthtest);
1857 Cvar_RegisterVariable(&r_drawportals);
1858 Cvar_RegisterVariable(&r_drawentities);
1859 Cvar_RegisterVariable(&r_cullentities_trace);
1860 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1861 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1862 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1863 Cvar_RegisterVariable(&r_drawviewmodel);
1864 Cvar_RegisterVariable(&r_speeds);
1865 Cvar_RegisterVariable(&r_fullbrights);
1866 Cvar_RegisterVariable(&r_wateralpha);
1867 Cvar_RegisterVariable(&r_dynamic);
1868 Cvar_RegisterVariable(&r_fullbright);
1869 Cvar_RegisterVariable(&r_shadows);
1870 Cvar_RegisterVariable(&r_shadows_throwdistance);
1871 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1872 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1873 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1874 Cvar_RegisterVariable(&r_textureunits);
1875 Cvar_RegisterVariable(&r_glsl);
1876 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1877 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1878 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1879 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1880 Cvar_RegisterVariable(&r_water);
1881 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1882 Cvar_RegisterVariable(&r_water_clippingplanebias);
1883 Cvar_RegisterVariable(&r_water_refractdistort);
1884 Cvar_RegisterVariable(&r_water_reflectdistort);
1885 Cvar_RegisterVariable(&r_lerpsprites);
1886 Cvar_RegisterVariable(&r_lerpmodels);
1887 Cvar_RegisterVariable(&r_waterscroll);
1888 Cvar_RegisterVariable(&r_bloom);
1889 Cvar_RegisterVariable(&r_bloom_colorscale);
1890 Cvar_RegisterVariable(&r_bloom_brighten);
1891 Cvar_RegisterVariable(&r_bloom_blur);
1892 Cvar_RegisterVariable(&r_bloom_resolution);
1893 Cvar_RegisterVariable(&r_bloom_colorexponent);
1894 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1895 Cvar_RegisterVariable(&r_hdr);
1896 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1897 Cvar_RegisterVariable(&r_glsl_contrastboost);
1898 Cvar_RegisterVariable(&r_hdr_glowintensity);
1899 Cvar_RegisterVariable(&r_hdr_range);
1900 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1901 Cvar_RegisterVariable(&developer_texturelogging);
1902 Cvar_RegisterVariable(&gl_lightmaps);
1903 Cvar_RegisterVariable(&r_test);
1904 Cvar_RegisterVariable(&r_batchmode);
1905 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1906 Cvar_SetValue("r_fullbrights", 0);
1907 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1909 Cvar_RegisterVariable(&r_track_sprites);
1910 Cvar_RegisterVariable(&r_track_sprites_flags);
1911 Cvar_RegisterVariable(&r_track_sprites_scalew);
1912 Cvar_RegisterVariable(&r_track_sprites_scaleh);
1915 extern void R_Textures_Init(void);
1916 extern void GL_Draw_Init(void);
1917 extern void GL_Main_Init(void);
1918 extern void R_Shadow_Init(void);
1919 extern void R_Sky_Init(void);
1920 extern void GL_Surf_Init(void);
1921 extern void R_Light_Init(void);
1922 extern void R_Particles_Init(void);
1923 extern void R_Explosion_Init(void);
1924 extern void gl_backend_init(void);
1925 extern void Sbar_Init(void);
1926 extern void R_LightningBeams_Init(void);
1927 extern void Mod_RenderInit(void);
1929 void Render_Init(void)
1942 R_LightningBeams_Init();
1951 extern char *ENGINE_EXTENSIONS;
1954 VID_CheckExtensions();
1956 // LordHavoc: report supported extensions
1957 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1959 // clear to black (loading plaque will be seen over this)
1961 qglClearColor(0,0,0,1);CHECKGLERROR
1962 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1965 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1969 for (i = 0;i < r_view.numfrustumplanes;i++)
1971 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1974 p = r_view.frustum + i;
1979 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1983 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1987 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1991 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1995 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1999 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2003 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2007 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2015 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2019 for (i = 0;i < numplanes;i++)
2026 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2030 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2034 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2038 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2042 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2046 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2050 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2054 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2062 //==================================================================================
2064 static void R_UpdateEntityLighting(entity_render_t *ent)
2066 vec3_t tempdiffusenormal;
2068 // fetch the lighting from the worldmodel data
2069 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));
2070 VectorClear(ent->modellight_diffuse);
2071 VectorClear(tempdiffusenormal);
2072 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2075 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2076 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2079 VectorSet(ent->modellight_ambient, 1, 1, 1);
2081 // move the light direction into modelspace coordinates for lighting code
2082 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2083 if(VectorLength2(ent->modellight_lightdir) > 0)
2085 VectorNormalize(ent->modellight_lightdir);
2089 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2092 // scale ambient and directional light contributions according to rendering variables
2093 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2094 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2095 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2096 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2097 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2098 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2101 static void R_View_UpdateEntityVisible (void)
2104 entity_render_t *ent;
2106 if (!r_drawentities.integer)
2109 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2110 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2112 // worldmodel can check visibility
2113 for (i = 0;i < r_refdef.numentities;i++)
2115 ent = r_refdef.entities[i];
2116 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !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));
2119 if(r_cullentities_trace.integer)
2121 for (i = 0;i < r_refdef.numentities;i++)
2123 ent = r_refdef.entities[i];
2124 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2126 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2127 ent->last_trace_visibility = realtime;
2128 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2129 r_viewcache.entityvisible[i] = 0;
2136 // no worldmodel or it can't check visibility
2137 for (i = 0;i < r_refdef.numentities;i++)
2139 ent = r_refdef.entities[i];
2140 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2144 // update entity lighting (even on hidden entities for r_shadows)
2145 for (i = 0;i < r_refdef.numentities;i++)
2146 R_UpdateEntityLighting(r_refdef.entities[i]);
2149 // only used if skyrendermasked, and normally returns false
2150 int R_DrawBrushModelsSky (void)
2153 entity_render_t *ent;
2155 if (!r_drawentities.integer)
2159 for (i = 0;i < r_refdef.numentities;i++)
2161 if (!r_viewcache.entityvisible[i])
2163 ent = r_refdef.entities[i];
2164 if (!ent->model || !ent->model->DrawSky)
2166 ent->model->DrawSky(ent);
2172 static void R_DrawNoModel(entity_render_t *ent);
2173 static void R_DrawModels(void)
2176 entity_render_t *ent;
2178 if (!r_drawentities.integer)
2181 for (i = 0;i < r_refdef.numentities;i++)
2183 if (!r_viewcache.entityvisible[i])
2185 ent = r_refdef.entities[i];
2186 r_refdef.stats.entities++;
2187 if (ent->model && ent->model->Draw != NULL)
2188 ent->model->Draw(ent);
2194 static void R_DrawModelsDepth(void)
2197 entity_render_t *ent;
2199 if (!r_drawentities.integer)
2202 for (i = 0;i < r_refdef.numentities;i++)
2204 if (!r_viewcache.entityvisible[i])
2206 ent = r_refdef.entities[i];
2207 r_refdef.stats.entities++;
2208 if (ent->model && ent->model->DrawDepth != NULL)
2209 ent->model->DrawDepth(ent);
2213 static void R_DrawModelsDebug(void)
2216 entity_render_t *ent;
2218 if (!r_drawentities.integer)
2221 for (i = 0;i < r_refdef.numentities;i++)
2223 if (!r_viewcache.entityvisible[i])
2225 ent = r_refdef.entities[i];
2226 r_refdef.stats.entities++;
2227 if (ent->model && ent->model->DrawDebug != NULL)
2228 ent->model->DrawDebug(ent);
2232 static void R_DrawModelsAddWaterPlanes(void)
2235 entity_render_t *ent;
2237 if (!r_drawentities.integer)
2240 for (i = 0;i < r_refdef.numentities;i++)
2242 if (!r_viewcache.entityvisible[i])
2244 ent = r_refdef.entities[i];
2245 r_refdef.stats.entities++;
2246 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2247 ent->model->DrawAddWaterPlanes(ent);
2251 static void R_View_SetFrustum(void)
2254 double slopex, slopey;
2256 // break apart the view matrix into vectors for various purposes
2257 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2258 VectorNegate(r_view.left, r_view.right);
2261 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2262 r_view.frustum[0].normal[1] = 0 - 0;
2263 r_view.frustum[0].normal[2] = -1 - 0;
2264 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2265 r_view.frustum[1].normal[1] = 0 + 0;
2266 r_view.frustum[1].normal[2] = -1 + 0;
2267 r_view.frustum[2].normal[0] = 0 - 0;
2268 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2269 r_view.frustum[2].normal[2] = -1 - 0;
2270 r_view.frustum[3].normal[0] = 0 + 0;
2271 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2272 r_view.frustum[3].normal[2] = -1 + 0;
2276 zNear = r_refdef.nearclip;
2277 nudge = 1.0 - 1.0 / (1<<23);
2278 r_view.frustum[4].normal[0] = 0 - 0;
2279 r_view.frustum[4].normal[1] = 0 - 0;
2280 r_view.frustum[4].normal[2] = -1 - -nudge;
2281 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2282 r_view.frustum[5].normal[0] = 0 + 0;
2283 r_view.frustum[5].normal[1] = 0 + 0;
2284 r_view.frustum[5].normal[2] = -1 + -nudge;
2285 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2291 r_view.frustum[0].normal[0] = m[3] - m[0];
2292 r_view.frustum[0].normal[1] = m[7] - m[4];
2293 r_view.frustum[0].normal[2] = m[11] - m[8];
2294 r_view.frustum[0].dist = m[15] - m[12];
2296 r_view.frustum[1].normal[0] = m[3] + m[0];
2297 r_view.frustum[1].normal[1] = m[7] + m[4];
2298 r_view.frustum[1].normal[2] = m[11] + m[8];
2299 r_view.frustum[1].dist = m[15] + m[12];
2301 r_view.frustum[2].normal[0] = m[3] - m[1];
2302 r_view.frustum[2].normal[1] = m[7] - m[5];
2303 r_view.frustum[2].normal[2] = m[11] - m[9];
2304 r_view.frustum[2].dist = m[15] - m[13];
2306 r_view.frustum[3].normal[0] = m[3] + m[1];
2307 r_view.frustum[3].normal[1] = m[7] + m[5];
2308 r_view.frustum[3].normal[2] = m[11] + m[9];
2309 r_view.frustum[3].dist = m[15] + m[13];
2311 r_view.frustum[4].normal[0] = m[3] - m[2];
2312 r_view.frustum[4].normal[1] = m[7] - m[6];
2313 r_view.frustum[4].normal[2] = m[11] - m[10];
2314 r_view.frustum[4].dist = m[15] - m[14];
2316 r_view.frustum[5].normal[0] = m[3] + m[2];
2317 r_view.frustum[5].normal[1] = m[7] + m[6];
2318 r_view.frustum[5].normal[2] = m[11] + m[10];
2319 r_view.frustum[5].dist = m[15] + m[14];
2322 if (r_view.useperspective)
2324 slopex = 1.0 / r_view.frustum_x;
2325 slopey = 1.0 / r_view.frustum_y;
2326 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2327 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2328 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2329 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2330 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2332 // Leaving those out was a mistake, those were in the old code, and they
2333 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2334 // I couldn't reproduce it after adding those normalizations. --blub
2335 VectorNormalize(r_view.frustum[0].normal);
2336 VectorNormalize(r_view.frustum[1].normal);
2337 VectorNormalize(r_view.frustum[2].normal);
2338 VectorNormalize(r_view.frustum[3].normal);
2340 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2341 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2342 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2343 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2344 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2346 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2347 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2348 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2349 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2350 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2354 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2355 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2356 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2357 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2358 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2359 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2360 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2361 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2362 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2363 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2365 r_view.numfrustumplanes = 5;
2367 if (r_view.useclipplane)
2369 r_view.numfrustumplanes = 6;
2370 r_view.frustum[5] = r_view.clipplane;
2373 for (i = 0;i < r_view.numfrustumplanes;i++)
2374 PlaneClassify(r_view.frustum + i);
2376 // LordHavoc: note to all quake engine coders, Quake had a special case
2377 // for 90 degrees which assumed a square view (wrong), so I removed it,
2378 // Quake2 has it disabled as well.
2380 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2381 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2382 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2383 //PlaneClassify(&frustum[0]);
2385 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2386 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2387 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2388 //PlaneClassify(&frustum[1]);
2390 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2391 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2392 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2393 //PlaneClassify(&frustum[2]);
2395 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2396 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2397 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2398 //PlaneClassify(&frustum[3]);
2401 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2402 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2403 //PlaneClassify(&frustum[4]);
2406 void R_View_Update(void)
2408 R_View_SetFrustum();
2409 R_View_WorldVisibility(r_view.useclipplane);
2410 R_View_UpdateEntityVisible();
2413 void R_SetupView(void)
2415 if (!r_view.useperspective)
2416 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);
2417 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2418 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2420 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2422 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2424 if (r_view.useclipplane)
2426 // LordHavoc: couldn't figure out how to make this approach the
2427 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2428 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2429 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2430 dist = r_view.clipplane.dist;
2431 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2435 void R_ResetViewRendering2D(void)
2437 if (gl_support_fragment_shader)
2439 qglUseProgramObjectARB(0);CHECKGLERROR
2444 // GL is weird because it's bottom to top, r_view.y is top to bottom
2445 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2446 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2447 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2448 GL_Color(1, 1, 1, 1);
2449 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2450 GL_BlendFunc(GL_ONE, GL_ZERO);
2451 GL_AlphaTest(false);
2452 GL_ScissorTest(false);
2453 GL_DepthMask(false);
2454 GL_DepthRange(0, 1);
2455 GL_DepthTest(false);
2456 R_Mesh_Matrix(&identitymatrix);
2457 R_Mesh_ResetTextureState();
2458 GL_PolygonOffset(0, 0);
2459 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2460 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2461 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2462 qglStencilMask(~0);CHECKGLERROR
2463 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2464 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2465 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2468 void R_ResetViewRendering3D(void)
2470 if (gl_support_fragment_shader)
2472 qglUseProgramObjectARB(0);CHECKGLERROR
2477 // GL is weird because it's bottom to top, r_view.y is top to bottom
2478 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2480 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2481 GL_Color(1, 1, 1, 1);
2482 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2483 GL_BlendFunc(GL_ONE, GL_ZERO);
2484 GL_AlphaTest(false);
2485 GL_ScissorTest(true);
2487 GL_DepthRange(0, 1);
2489 R_Mesh_Matrix(&identitymatrix);
2490 R_Mesh_ResetTextureState();
2491 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2492 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2493 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2494 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2495 qglStencilMask(~0);CHECKGLERROR
2496 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2497 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2498 GL_CullFace(r_view.cullface_back);
2502 R_Bloom_SetupShader(
2504 "// written by Forest 'LordHavoc' Hale\n"
2506 "// common definitions between vertex shader and fragment shader:\n"
2508 "#ifdef __GLSL_CG_DATA_TYPES\n"
2509 "#define myhalf half\n"
2510 "#define myhvec2 hvec2\n"
2511 "#define myhvec3 hvec3\n"
2512 "#define myhvec4 hvec4\n"
2514 "#define myhalf float\n"
2515 "#define myhvec2 vec2\n"
2516 "#define myhvec3 vec3\n"
2517 "#define myhvec4 vec4\n"
2520 "varying vec2 ScreenTexCoord;\n"
2521 "varying vec2 BloomTexCoord;\n"
2526 "// vertex shader specific:\n"
2527 "#ifdef VERTEX_SHADER\n"
2531 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2532 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2533 " // transform vertex to camera space, using ftransform to match non-VS\n"
2535 " gl_Position = ftransform();\n"
2538 "#endif // VERTEX_SHADER\n"
2543 "// fragment shader specific:\n"
2544 "#ifdef FRAGMENT_SHADER\n"
2549 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2550 " for (x = -BLUR_X;x <= BLUR_X;x++)
2551 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2552 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2553 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2554 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2556 " gl_FragColor = vec4(color);\n"
2559 "#endif // FRAGMENT_SHADER\n"
2562 void R_RenderScene(qboolean addwaterplanes);
2564 static void R_Water_StartFrame(void)
2567 int waterwidth, waterheight, texturewidth, textureheight;
2568 r_waterstate_waterplane_t *p;
2570 // set waterwidth and waterheight to the water resolution that will be
2571 // used (often less than the screen resolution for faster rendering)
2572 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2573 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2575 // calculate desired texture sizes
2576 // can't use water if the card does not support the texture size
2577 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2578 texturewidth = textureheight = waterwidth = waterheight = 0;
2579 else if (gl_support_arb_texture_non_power_of_two)
2581 texturewidth = waterwidth;
2582 textureheight = waterheight;
2586 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2587 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2590 // allocate textures as needed
2591 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2593 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2594 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2596 if (p->texture_refraction)
2597 R_FreeTexture(p->texture_refraction);
2598 p->texture_refraction = NULL;
2599 if (p->texture_reflection)
2600 R_FreeTexture(p->texture_reflection);
2601 p->texture_reflection = NULL;
2603 memset(&r_waterstate, 0, sizeof(r_waterstate));
2604 r_waterstate.waterwidth = waterwidth;
2605 r_waterstate.waterheight = waterheight;
2606 r_waterstate.texturewidth = texturewidth;
2607 r_waterstate.textureheight = textureheight;
2610 if (r_waterstate.waterwidth)
2612 r_waterstate.enabled = true;
2614 // set up variables that will be used in shader setup
2615 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2616 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2617 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2618 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2621 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2622 r_waterstate.numwaterplanes = 0;
2625 static void R_Water_AddWaterPlane(msurface_t *surface)
2627 int triangleindex, planeindex;
2633 r_waterstate_waterplane_t *p;
2634 // just use the first triangle with a valid normal for any decisions
2635 VectorClear(normal);
2636 VectorClear(center);
2637 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2639 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2640 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2641 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2642 TriangleNormal(vert[0], vert[1], vert[2], normal);
2643 if (VectorLength2(normal) >= 0.001)
2646 // now find the center of this surface
2647 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2649 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2650 VectorAdd(center, vert[0], center);
2652 f = 1.0 / surface->num_triangles*3;
2653 VectorScale(center, f, center);
2655 // find a matching plane if there is one
2656 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2657 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2659 if (planeindex >= r_waterstate.maxwaterplanes)
2660 return; // nothing we can do, out of planes
2662 // if this triangle does not fit any known plane rendered this frame, add one
2663 if (planeindex >= r_waterstate.numwaterplanes)
2665 // store the new plane
2666 r_waterstate.numwaterplanes++;
2667 VectorCopy(normal, p->plane.normal);
2668 VectorNormalize(p->plane.normal);
2669 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2670 PlaneClassify(&p->plane);
2671 // flip the plane if it does not face the viewer
2672 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2674 VectorNegate(p->plane.normal, p->plane.normal);
2675 p->plane.dist *= -1;
2676 PlaneClassify(&p->plane);
2678 // clear materialflags and pvs
2679 p->materialflags = 0;
2680 p->pvsvalid = false;
2682 // merge this surface's materialflags into the waterplane
2683 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2684 // merge this surface's PVS into the waterplane
2685 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2687 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2692 static void R_Water_ProcessPlanes(void)
2694 r_view_t originalview;
2696 r_waterstate_waterplane_t *p;
2698 originalview = r_view;
2700 // make sure enough textures are allocated
2701 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2703 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2705 if (!p->texture_refraction)
2706 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);
2707 if (!p->texture_refraction)
2711 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2713 if (!p->texture_reflection)
2714 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);
2715 if (!p->texture_reflection)
2721 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2723 r_view.showdebug = false;
2724 r_view.width = r_waterstate.waterwidth;
2725 r_view.height = r_waterstate.waterheight;
2726 r_view.useclipplane = true;
2727 r_waterstate.renderingscene = true;
2729 // render the normal view scene and copy into texture
2730 // (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)
2731 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2733 r_view.clipplane = p->plane;
2734 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2735 r_view.clipplane.dist = -r_view.clipplane.dist;
2736 PlaneClassify(&r_view.clipplane);
2738 R_RenderScene(false);
2740 // copy view into the screen texture
2741 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2742 GL_ActiveTexture(0);
2744 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
2747 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2749 // render reflected scene and copy into texture
2750 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2751 r_view.clipplane = p->plane;
2752 // reverse the cullface settings for this render
2753 r_view.cullface_front = GL_FRONT;
2754 r_view.cullface_back = GL_BACK;
2755 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2757 r_view.usecustompvs = true;
2759 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2761 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2764 R_ResetViewRendering3D();
2766 if (r_timereport_active)
2767 R_TimeReport("viewclear");
2769 R_RenderScene(false);
2771 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2772 GL_ActiveTexture(0);
2774 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
2776 R_ResetViewRendering3D();
2778 if (r_timereport_active)
2779 R_TimeReport("viewclear");
2782 r_view = originalview;
2783 r_view.clear = true;
2784 r_waterstate.renderingscene = false;
2788 r_view = originalview;
2789 r_waterstate.renderingscene = false;
2790 Cvar_SetValueQuick(&r_water, 0);
2791 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2795 void R_Bloom_StartFrame(void)
2797 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2799 // set bloomwidth and bloomheight to the bloom resolution that will be
2800 // used (often less than the screen resolution for faster rendering)
2801 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2802 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2803 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2805 // calculate desired texture sizes
2806 if (gl_support_arb_texture_non_power_of_two)
2808 screentexturewidth = r_view.width;
2809 screentextureheight = r_view.height;
2810 bloomtexturewidth = r_bloomstate.bloomwidth;
2811 bloomtextureheight = r_bloomstate.bloomheight;
2815 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2816 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2817 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2818 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2823 screentexturewidth = screentextureheight = 0;
2825 else if (r_bloom.integer)
2830 screentexturewidth = screentextureheight = 0;
2831 bloomtexturewidth = bloomtextureheight = 0;
2834 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)
2836 // can't use bloom if the parameters are too weird
2837 // can't use bloom if the card does not support the texture size
2838 if (r_bloomstate.texture_screen)
2839 R_FreeTexture(r_bloomstate.texture_screen);
2840 if (r_bloomstate.texture_bloom)
2841 R_FreeTexture(r_bloomstate.texture_bloom);
2842 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2846 r_bloomstate.enabled = true;
2847 r_bloomstate.hdr = r_hdr.integer != 0;
2849 // allocate textures as needed
2850 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2852 if (r_bloomstate.texture_screen)
2853 R_FreeTexture(r_bloomstate.texture_screen);
2854 r_bloomstate.texture_screen = NULL;
2855 r_bloomstate.screentexturewidth = screentexturewidth;
2856 r_bloomstate.screentextureheight = screentextureheight;
2857 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2858 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);
2860 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2862 if (r_bloomstate.texture_bloom)
2863 R_FreeTexture(r_bloomstate.texture_bloom);
2864 r_bloomstate.texture_bloom = NULL;
2865 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2866 r_bloomstate.bloomtextureheight = bloomtextureheight;
2867 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2868 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);
2871 // set up a texcoord array for the full resolution screen image
2872 // (we have to keep this around to copy back during final render)
2873 r_bloomstate.screentexcoord2f[0] = 0;
2874 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2875 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2876 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2877 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2878 r_bloomstate.screentexcoord2f[5] = 0;
2879 r_bloomstate.screentexcoord2f[6] = 0;
2880 r_bloomstate.screentexcoord2f[7] = 0;
2882 // set up a texcoord array for the reduced resolution bloom image
2883 // (which will be additive blended over the screen image)
2884 r_bloomstate.bloomtexcoord2f[0] = 0;
2885 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2886 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2887 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2888 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2889 r_bloomstate.bloomtexcoord2f[5] = 0;
2890 r_bloomstate.bloomtexcoord2f[6] = 0;
2891 r_bloomstate.bloomtexcoord2f[7] = 0;
2894 void R_Bloom_CopyScreenTexture(float colorscale)
2896 r_refdef.stats.bloom++;
2898 R_ResetViewRendering2D();
2899 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2900 R_Mesh_ColorPointer(NULL, 0, 0);
2901 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2902 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2904 // copy view into the screen texture
2905 GL_ActiveTexture(0);
2907 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
2908 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2910 // now scale it down to the bloom texture size
2912 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2913 GL_BlendFunc(GL_ONE, GL_ZERO);
2914 GL_Color(colorscale, colorscale, colorscale, 1);
2915 // TODO: optimize with multitexture or GLSL
2916 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2917 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2919 // we now have a bloom image in the framebuffer
2920 // copy it into the bloom image texture for later processing
2921 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2922 GL_ActiveTexture(0);
2924 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
2925 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2928 void R_Bloom_CopyHDRTexture(void)
2930 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2931 GL_ActiveTexture(0);
2933 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
2934 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2937 void R_Bloom_MakeTexture(void)
2940 float xoffset, yoffset, r, brighten;
2942 r_refdef.stats.bloom++;
2944 R_ResetViewRendering2D();
2945 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2946 R_Mesh_ColorPointer(NULL, 0, 0);
2948 // we have a bloom image in the framebuffer
2950 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2952 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2955 r = bound(0, r_bloom_colorexponent.value / x, 1);
2956 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2957 GL_Color(r, r, r, 1);
2958 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2959 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2960 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2961 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2963 // copy the vertically blurred bloom view to a texture
2964 GL_ActiveTexture(0);
2966 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
2967 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2970 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2971 brighten = r_bloom_brighten.value;
2973 brighten *= r_hdr_range.value;
2974 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2975 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2977 for (dir = 0;dir < 2;dir++)
2979 // blend on at multiple vertical offsets to achieve a vertical blur
2980 // TODO: do offset blends using GLSL
2981 GL_BlendFunc(GL_ONE, GL_ZERO);
2982 for (x = -range;x <= range;x++)
2984 if (!dir){xoffset = 0;yoffset = x;}
2985 else {xoffset = x;yoffset = 0;}
2986 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2987 yoffset /= (float)r_bloomstate.bloomtextureheight;
2988 // compute a texcoord array with the specified x and y offset
2989 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2990 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2991 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2992 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2993 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2994 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2995 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2996 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2997 // this r value looks like a 'dot' particle, fading sharply to
2998 // black at the edges
2999 // (probably not realistic but looks good enough)
3000 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3001 //r = (dir ? 1.0f : brighten)/(range*2+1);
3002 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3003 GL_Color(r, r, r, 1);
3004 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3005 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3006 GL_BlendFunc(GL_ONE, GL_ONE);
3009 // copy the vertically blurred bloom view to a texture
3010 GL_ActiveTexture(0);
3012 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
3013 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3016 // apply subtract last
3017 // (just like it would be in a GLSL shader)
3018 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3020 GL_BlendFunc(GL_ONE, GL_ZERO);
3021 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3022 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3023 GL_Color(1, 1, 1, 1);
3024 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3025 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3027 GL_BlendFunc(GL_ONE, GL_ONE);
3028 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3029 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3030 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3031 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3032 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3033 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3034 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3036 // copy the darkened bloom view to a texture
3037 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3038 GL_ActiveTexture(0);
3040 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
3041 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3045 void R_HDR_RenderBloomTexture(void)
3047 int oldwidth, oldheight;
3049 oldwidth = r_view.width;
3050 oldheight = r_view.height;
3051 r_view.width = r_bloomstate.bloomwidth;
3052 r_view.height = r_bloomstate.bloomheight;
3054 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3055 // TODO: add exposure compensation features
3056 // TODO: add fp16 framebuffer support
3058 r_view.showdebug = false;
3059 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3061 r_view.colorscale /= r_hdr_range.value;
3062 r_waterstate.numwaterplanes = 0;
3063 R_RenderScene(r_waterstate.enabled);
3064 r_view.showdebug = true;
3066 R_ResetViewRendering2D();
3068 R_Bloom_CopyHDRTexture();
3069 R_Bloom_MakeTexture();
3071 R_ResetViewRendering3D();
3074 if (r_timereport_active)
3075 R_TimeReport("viewclear");
3077 // restore the view settings
3078 r_view.width = oldwidth;
3079 r_view.height = oldheight;
3082 static void R_BlendView(void)
3084 if (r_bloomstate.enabled && r_bloomstate.hdr)
3086 // render high dynamic range bloom effect
3087 // the bloom texture was made earlier this render, so we just need to
3088 // blend it onto the screen...
3089 R_ResetViewRendering2D();
3090 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3091 R_Mesh_ColorPointer(NULL, 0, 0);
3092 GL_Color(1, 1, 1, 1);
3093 GL_BlendFunc(GL_ONE, GL_ONE);
3094 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3095 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3096 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3097 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3099 else if (r_bloomstate.enabled)
3101 // render simple bloom effect
3102 // copy the screen and shrink it and darken it for the bloom process
3103 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3104 // make the bloom texture
3105 R_Bloom_MakeTexture();
3106 // put the original screen image back in place and blend the bloom
3108 R_ResetViewRendering2D();
3109 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3110 R_Mesh_ColorPointer(NULL, 0, 0);
3111 GL_Color(1, 1, 1, 1);
3112 GL_BlendFunc(GL_ONE, GL_ZERO);
3113 // do both in one pass if possible
3114 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3115 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3116 if (r_textureunits.integer >= 2 && gl_combine.integer)
3118 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3119 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3120 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3124 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3125 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3126 // now blend on the bloom texture
3127 GL_BlendFunc(GL_ONE, GL_ONE);
3128 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3129 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3131 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3132 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3134 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3136 // apply a color tint to the whole view
3137 R_ResetViewRendering2D();
3138 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3139 R_Mesh_ColorPointer(NULL, 0, 0);
3140 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3141 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3142 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3146 void R_RenderScene(qboolean addwaterplanes);
3148 matrix4x4_t r_waterscrollmatrix;
3150 void R_UpdateVariables(void)
3154 r_refdef.farclip = 4096;
3155 if (r_refdef.worldmodel)
3156 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3157 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3159 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3160 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3161 r_refdef.polygonfactor = 0;
3162 r_refdef.polygonoffset = 0;
3163 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3164 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3166 r_refdef.rtworld = r_shadow_realtime_world.integer;
3167 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3168 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3169 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3170 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3171 if (r_showsurfaces.integer)
3173 r_refdef.rtworld = false;
3174 r_refdef.rtworldshadows = false;
3175 r_refdef.rtdlight = false;
3176 r_refdef.rtdlightshadows = false;
3177 r_refdef.lightmapintensity = 0;
3180 if (gamemode == GAME_NEHAHRA)
3182 if (gl_fogenable.integer)
3184 r_refdef.oldgl_fogenable = true;
3185 r_refdef.fog_density = gl_fogdensity.value;
3186 r_refdef.fog_red = gl_fogred.value;
3187 r_refdef.fog_green = gl_foggreen.value;
3188 r_refdef.fog_blue = gl_fogblue.value;
3190 else if (r_refdef.oldgl_fogenable)
3192 r_refdef.oldgl_fogenable = false;
3193 r_refdef.fog_density = 0;
3194 r_refdef.fog_red = 0;
3195 r_refdef.fog_green = 0;
3196 r_refdef.fog_blue = 0;
3199 if (r_refdef.fog_density)
3201 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3202 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3203 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3205 if (r_refdef.fog_density)
3207 r_refdef.fogenabled = true;
3208 // this is the point where the fog reaches 0.9986 alpha, which we
3209 // consider a good enough cutoff point for the texture
3210 // (0.9986 * 256 == 255.6)
3211 r_refdef.fogrange = 400 / r_refdef.fog_density;
3212 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3213 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3214 // fog color was already set
3217 r_refdef.fogenabled = false;
3225 void R_RenderView(void)
3227 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3228 return; //Host_Error ("R_RenderView: NULL worldmodel");
3230 R_Shadow_UpdateWorldLightSelection();
3232 R_Bloom_StartFrame();
3233 R_Water_StartFrame();
3236 if (r_timereport_active)
3237 R_TimeReport("viewsetup");
3239 R_ResetViewRendering3D();
3244 if (r_timereport_active)
3245 R_TimeReport("viewclear");
3247 r_view.clear = true;
3249 r_view.showdebug = true;
3251 // this produces a bloom texture to be used in R_BlendView() later
3253 R_HDR_RenderBloomTexture();
3255 r_view.colorscale = r_hdr_scenebrightness.value;
3256 r_waterstate.numwaterplanes = 0;
3257 R_RenderScene(r_waterstate.enabled);
3260 if (r_timereport_active)
3261 R_TimeReport("blendview");
3263 GL_Scissor(0, 0, vid.width, vid.height);
3264 GL_ScissorTest(false);
3268 extern void R_DrawLightningBeams (void);
3269 extern void VM_CL_AddPolygonsToMeshQueue (void);
3270 extern void R_DrawPortals (void);
3271 extern cvar_t cl_locs_show;
3272 static void R_DrawLocs(void);
3273 static void R_DrawEntityBBoxes(void);
3274 void R_RenderScene(qboolean addwaterplanes)
3278 R_ResetViewRendering3D();
3281 if (r_timereport_active)
3282 R_TimeReport("watervis");
3284 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3286 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3287 if (r_timereport_active)
3288 R_TimeReport("waterworld");
3291 // don't let sound skip if going slow
3292 if (r_refdef.extraupdate)
3295 R_DrawModelsAddWaterPlanes();
3296 if (r_timereport_active)
3297 R_TimeReport("watermodels");
3299 R_Water_ProcessPlanes();
3300 if (r_timereport_active)
3301 R_TimeReport("waterscenes");
3304 R_ResetViewRendering3D();
3306 // don't let sound skip if going slow
3307 if (r_refdef.extraupdate)
3310 R_MeshQueue_BeginScene();
3315 if (r_timereport_active)
3316 R_TimeReport("visibility");
3318 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);
3320 if (cl.csqc_vidvars.drawworld)
3322 // don't let sound skip if going slow
3323 if (r_refdef.extraupdate)
3326 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3328 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3329 if (r_timereport_active)
3330 R_TimeReport("worldsky");
3333 if (R_DrawBrushModelsSky() && r_timereport_active)
3334 R_TimeReport("bmodelsky");
3337 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3339 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3340 if (r_timereport_active)
3341 R_TimeReport("worlddepth");
3343 if (r_depthfirst.integer >= 2)
3345 R_DrawModelsDepth();
3346 if (r_timereport_active)
3347 R_TimeReport("modeldepth");
3350 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3352 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3353 if (r_timereport_active)
3354 R_TimeReport("world");
3357 // don't let sound skip if going slow
3358 if (r_refdef.extraupdate)
3362 if (r_timereport_active)
3363 R_TimeReport("models");
3365 // don't let sound skip if going slow
3366 if (r_refdef.extraupdate)
3369 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3371 R_DrawModelShadows();
3373 R_ResetViewRendering3D();
3375 // don't let sound skip if going slow
3376 if (r_refdef.extraupdate)
3380 R_ShadowVolumeLighting(false);
3381 if (r_timereport_active)
3382 R_TimeReport("rtlights");
3384 // don't let sound skip if going slow
3385 if (r_refdef.extraupdate)
3388 if (cl.csqc_vidvars.drawworld)
3390 R_DrawLightningBeams();
3391 if (r_timereport_active)
3392 R_TimeReport("lightning");
3395 if (r_timereport_active)
3396 R_TimeReport("particles");
3399 if (r_timereport_active)
3400 R_TimeReport("explosions");
3403 if (gl_support_fragment_shader)
3405 qglUseProgramObjectARB(0);CHECKGLERROR
3407 VM_CL_AddPolygonsToMeshQueue();
3409 if (r_view.showdebug)
3411 if (cl_locs_show.integer)
3414 if (r_timereport_active)
3415 R_TimeReport("showlocs");
3418 if (r_drawportals.integer)
3421 if (r_timereport_active)
3422 R_TimeReport("portals");
3425 if (r_showbboxes.value > 0)
3427 R_DrawEntityBBoxes();
3428 if (r_timereport_active)
3429 R_TimeReport("bboxes");
3433 if (gl_support_fragment_shader)
3435 qglUseProgramObjectARB(0);CHECKGLERROR
3437 R_MeshQueue_RenderTransparent();
3438 if (r_timereport_active)
3439 R_TimeReport("drawtrans");
3441 if (gl_support_fragment_shader)
3443 qglUseProgramObjectARB(0);CHECKGLERROR
3446 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3448 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3449 if (r_timereport_active)
3450 R_TimeReport("worlddebug");
3451 R_DrawModelsDebug();
3452 if (r_timereport_active)
3453 R_TimeReport("modeldebug");
3456 if (gl_support_fragment_shader)
3458 qglUseProgramObjectARB(0);CHECKGLERROR
3461 if (cl.csqc_vidvars.drawworld)
3464 if (r_timereport_active)
3465 R_TimeReport("coronas");
3468 // don't let sound skip if going slow
3469 if (r_refdef.extraupdate)
3472 R_ResetViewRendering2D();
3475 static const int bboxelements[36] =
3485 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3488 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3489 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3490 GL_DepthMask(false);
3491 GL_DepthRange(0, 1);
3492 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3493 R_Mesh_Matrix(&identitymatrix);
3494 R_Mesh_ResetTextureState();
3496 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3497 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3498 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3499 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3500 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3501 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3502 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3503 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3504 R_FillColors(color4f, 8, cr, cg, cb, ca);
3505 if (r_refdef.fogenabled)
3507 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3509 f1 = FogPoint_World(v);
3511 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3512 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3513 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3516 R_Mesh_VertexPointer(vertex3f, 0, 0);
3517 R_Mesh_ColorPointer(color4f, 0, 0);
3518 R_Mesh_ResetTextureState();
3519 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3522 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3526 prvm_edict_t *edict;
3527 // this function draws bounding boxes of server entities
3531 for (i = 0;i < numsurfaces;i++)
3533 edict = PRVM_EDICT_NUM(surfacelist[i]);
3534 switch ((int)edict->fields.server->solid)
3536 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3537 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3538 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3539 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3540 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3541 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3543 color[3] *= r_showbboxes.value;
3544 color[3] = bound(0, color[3], 1);
3545 GL_DepthTest(!r_showdisabledepthtest.integer);
3546 GL_CullFace(r_view.cullface_front);
3547 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3552 static void R_DrawEntityBBoxes(void)
3555 prvm_edict_t *edict;
3557 // this function draws bounding boxes of server entities
3561 for (i = 0;i < prog->num_edicts;i++)
3563 edict = PRVM_EDICT_NUM(i);
3564 if (edict->priv.server->free)
3566 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3567 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3572 int nomodelelements[24] =
3584 float nomodelvertex3f[6*3] =
3594 float nomodelcolor4f[6*4] =
3596 0.0f, 0.0f, 0.5f, 1.0f,
3597 0.0f, 0.0f, 0.5f, 1.0f,
3598 0.0f, 0.5f, 0.0f, 1.0f,
3599 0.0f, 0.5f, 0.0f, 1.0f,
3600 0.5f, 0.0f, 0.0f, 1.0f,
3601 0.5f, 0.0f, 0.0f, 1.0f
3604 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3609 // this is only called once per entity so numsurfaces is always 1, and
3610 // surfacelist is always {0}, so this code does not handle batches
3611 R_Mesh_Matrix(&ent->matrix);
3613 if (ent->flags & EF_ADDITIVE)
3615 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3616 GL_DepthMask(false);
3618 else if (ent->alpha < 1)
3620 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3621 GL_DepthMask(false);
3625 GL_BlendFunc(GL_ONE, GL_ZERO);
3628 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3629 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3630 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3631 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3632 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3633 if (r_refdef.fogenabled)
3636 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3637 R_Mesh_ColorPointer(color4f, 0, 0);
3638 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3639 f1 = FogPoint_World(org);
3641 for (i = 0, c = color4f;i < 6;i++, c += 4)
3643 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3644 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3645 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3649 else if (ent->alpha != 1)
3651 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3652 R_Mesh_ColorPointer(color4f, 0, 0);
3653 for (i = 0, c = color4f;i < 6;i++, c += 4)
3657 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3658 R_Mesh_ResetTextureState();
3659 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3662 void R_DrawNoModel(entity_render_t *ent)
3665 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3666 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3667 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3669 // R_DrawNoModelCallback(ent, 0);
3672 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3674 vec3_t right1, right2, diff, normal;
3676 VectorSubtract (org2, org1, normal);
3678 // calculate 'right' vector for start
3679 VectorSubtract (r_view.origin, org1, diff);
3680 CrossProduct (normal, diff, right1);
3681 VectorNormalize (right1);
3683 // calculate 'right' vector for end
3684 VectorSubtract (r_view.origin, org2, diff);
3685 CrossProduct (normal, diff, right2);
3686 VectorNormalize (right2);
3688 vert[ 0] = org1[0] + width * right1[0];
3689 vert[ 1] = org1[1] + width * right1[1];
3690 vert[ 2] = org1[2] + width * right1[2];
3691 vert[ 3] = org1[0] - width * right1[0];
3692 vert[ 4] = org1[1] - width * right1[1];
3693 vert[ 5] = org1[2] - width * right1[2];
3694 vert[ 6] = org2[0] - width * right2[0];
3695 vert[ 7] = org2[1] - width * right2[1];
3696 vert[ 8] = org2[2] - width * right2[2];
3697 vert[ 9] = org2[0] + width * right2[0];
3698 vert[10] = org2[1] + width * right2[1];
3699 vert[11] = org2[2] + width * right2[2];
3702 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3704 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)
3709 if (r_refdef.fogenabled)
3710 fog = FogPoint_World(origin);
3712 R_Mesh_Matrix(&identitymatrix);
3713 GL_BlendFunc(blendfunc1, blendfunc2);
3719 GL_CullFace(r_view.cullface_front);
3722 GL_CullFace(r_view.cullface_back);
3724 GL_DepthMask(false);
3725 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3726 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3727 GL_DepthTest(!depthdisable);
3729 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3730 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3731 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3732 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3733 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3734 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3735 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3736 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3737 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3738 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3739 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3740 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3742 R_Mesh_VertexPointer(vertex3f, 0, 0);
3743 R_Mesh_ColorPointer(NULL, 0, 0);
3744 R_Mesh_ResetTextureState();
3745 R_Mesh_TexBind(0, R_GetTexture(texture));
3746 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3747 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3748 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3749 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3751 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3753 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3754 GL_BlendFunc(blendfunc1, GL_ONE);
3756 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);
3757 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3761 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3766 VectorSet(v, x, y, z);
3767 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3768 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3770 if (i == mesh->numvertices)
3772 if (mesh->numvertices < mesh->maxvertices)
3774 VectorCopy(v, vertex3f);
3775 mesh->numvertices++;
3777 return mesh->numvertices;
3783 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3787 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3788 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3789 e = mesh->element3i + mesh->numtriangles * 3;
3790 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3792 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3793 if (mesh->numtriangles < mesh->maxtriangles)
3798 mesh->numtriangles++;
3800 element[1] = element[2];
3804 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3808 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3809 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3810 e = mesh->element3i + mesh->numtriangles * 3;
3811 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3813 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3814 if (mesh->numtriangles < mesh->maxtriangles)
3819 mesh->numtriangles++;
3821 element[1] = element[2];
3825 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3826 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3828 int planenum, planenum2;
3831 mplane_t *plane, *plane2;
3833 double temppoints[2][256*3];
3834 // figure out how large a bounding box we need to properly compute this brush
3836 for (w = 0;w < numplanes;w++)
3837 maxdist = max(maxdist, planes[w].dist);
3838 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3839 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3840 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3844 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3845 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3847 if (planenum2 == planenum)
3849 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);
3852 if (tempnumpoints < 3)
3854 // generate elements forming a triangle fan for this polygon
3855 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3859 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)
3861 texturelayer_t *layer;
3862 layer = t->currentlayers + t->currentnumlayers++;
3864 layer->depthmask = depthmask;
3865 layer->blendfunc1 = blendfunc1;
3866 layer->blendfunc2 = blendfunc2;
3867 layer->texture = texture;
3868 layer->texmatrix = *matrix;
3869 layer->color[0] = r * r_view.colorscale;
3870 layer->color[1] = g * r_view.colorscale;
3871 layer->color[2] = b * r_view.colorscale;
3872 layer->color[3] = a;
3875 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3878 index = parms[2] + r_refdef.time * parms[3];
3879 index -= floor(index);
3883 case Q3WAVEFUNC_NONE:
3884 case Q3WAVEFUNC_NOISE:
3885 case Q3WAVEFUNC_COUNT:
3888 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3889 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3890 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3891 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3892 case Q3WAVEFUNC_TRIANGLE:
3894 f = index - floor(index);
3905 return (float)(parms[0] + parms[1] * f);
3908 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3911 model_t *model = ent->model;
3914 q3shaderinfo_layer_tcmod_t *tcmod;
3916 // switch to an alternate material if this is a q1bsp animated material
3918 texture_t *texture = t;
3919 int s = ent->skinnum;
3920 if ((unsigned int)s >= (unsigned int)model->numskins)
3922 if (model->skinscenes)
3924 if (model->skinscenes[s].framecount > 1)
3925 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3927 s = model->skinscenes[s].firstframe;
3930 t = t + s * model->num_surfaces;
3933 // use an alternate animation if the entity's frame is not 0,
3934 // and only if the texture has an alternate animation
3935 if (ent->frame2 != 0 && t->anim_total[1])
3936 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3938 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3940 texture->currentframe = t;
3943 // update currentskinframe to be a qw skin or animation frame
3944 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3946 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3948 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3949 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3950 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);
3952 t->currentskinframe = r_qwskincache_skinframe[i];
3953 if (t->currentskinframe == NULL)
3954 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3956 else if (t->numskinframes >= 2)
3957 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3958 if (t->backgroundnumskinframes >= 2)
3959 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3961 t->currentmaterialflags = t->basematerialflags;
3962 t->currentalpha = ent->alpha;
3963 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3965 t->currentalpha *= r_wateralpha.value;
3967 * FIXME what is this supposed to do?
3968 // if rendering refraction/reflection, disable transparency
3969 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3970 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3973 if(!r_waterstate.enabled)
3974 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
3975 if (!(ent->flags & RENDER_LIGHT))
3976 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3977 if (ent->effects & EF_ADDITIVE)
3978 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3979 else if (t->currentalpha < 1)
3980 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3981 if (ent->effects & EF_DOUBLESIDED)
3982 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3983 if (ent->effects & EF_NODEPTHTEST)
3984 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3985 if (ent->flags & RENDER_VIEWMODEL)
3986 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3987 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3988 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3990 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3993 switch(tcmod->tcmod)
3997 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3998 matrix = r_waterscrollmatrix;
4000 matrix = identitymatrix;
4002 case Q3TCMOD_ENTITYTRANSLATE:
4003 // this is used in Q3 to allow the gamecode to control texcoord
4004 // scrolling on the entity, which is not supported in darkplaces yet.
4005 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4007 case Q3TCMOD_ROTATE:
4008 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4009 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4010 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4013 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4015 case Q3TCMOD_SCROLL:
4016 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4018 case Q3TCMOD_STRETCH:
4019 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4020 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4022 case Q3TCMOD_TRANSFORM:
4023 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4024 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4025 VectorSet(tcmat + 6, 0 , 0 , 1);
4026 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4027 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4029 case Q3TCMOD_TURBULENT:
4030 // this is handled in the RSurf_PrepareVertices function
4031 matrix = identitymatrix;
4034 // either replace or concatenate the transformation
4036 t->currenttexmatrix = matrix;
4039 matrix4x4_t temp = t->currenttexmatrix;
4040 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4044 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4045 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4046 t->glosstexture = r_texture_black;
4047 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4048 t->backgroundglosstexture = r_texture_black;
4049 t->specularpower = r_shadow_glossexponent.value;
4050 // TODO: store reference values for these in the texture?
4051 t->specularscale = 0;
4052 if (r_shadow_gloss.integer > 0)
4054 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4056 if (r_shadow_glossintensity.value > 0)
4058 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4059 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4060 t->specularscale = r_shadow_glossintensity.value;
4063 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4065 t->glosstexture = r_texture_white;
4066 t->backgroundglosstexture = r_texture_white;
4067 t->specularscale = r_shadow_gloss2intensity.value;
4071 // lightmaps mode looks bad with dlights using actual texturing, so turn
4072 // off the colormap and glossmap, but leave the normalmap on as it still
4073 // accurately represents the shading involved
4074 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4076 t->basetexture = r_texture_white;
4077 t->specularscale = 0;
4080 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4081 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4082 // submodels are biased to avoid z-fighting with world surfaces that they
4083 // may be exactly overlapping (avoids z-fighting artifacts on certain
4084 // doors and things in Quake maps)
4085 if (ent->model->brush.submodel)
4087 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4088 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4091 VectorClear(t->dlightcolor);
4092 t->currentnumlayers = 0;
4093 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4095 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4097 int blendfunc1, blendfunc2, depthmask;
4098 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4100 blendfunc1 = GL_SRC_ALPHA;
4101 blendfunc2 = GL_ONE;
4103 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4105 blendfunc1 = GL_SRC_ALPHA;
4106 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4108 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4110 blendfunc1 = t->customblendfunc[0];
4111 blendfunc2 = t->customblendfunc[1];
4115 blendfunc1 = GL_ONE;
4116 blendfunc2 = GL_ZERO;
4118 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4119 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4121 rtexture_t *currentbasetexture;
4123 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4124 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4125 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4126 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4128 // fullbright is not affected by r_refdef.lightmapintensity
4129 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4130 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4131 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
4132 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4133 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);
4138 // set the color tint used for lights affecting this surface
4139 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4141 // q3bsp has no lightmap updates, so the lightstylevalue that
4142 // would normally be baked into the lightmap must be
4143 // applied to the color
4144 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4145 if (ent->model->type == mod_brushq3)
4146 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4147 colorscale *= r_refdef.lightmapintensity;
4148 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);
4149 if (r_ambient.value >= (1.0f/64.0f))
4150 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);
4151 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4153 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);
4154 if (r_ambient.value >= (1.0f/64.0f))
4155 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);
4157 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4159 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);
4160 if (r_ambient.value >= (1.0f/64.0f))
4161 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);
4164 if (t->currentskinframe->glow != NULL)
4165 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);
4166 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4168 // if this is opaque use alpha blend which will darken the earlier
4171 // if this is an alpha blended material, all the earlier passes
4172 // were darkened by fog already, so we only need to add the fog
4173 // color ontop through the fog mask texture
4175 // if this is an additive blended material, all the earlier passes
4176 // were darkened by fog already, and we should not add fog color
4177 // (because the background was not darkened, there is no fog color
4178 // that was lost behind it).
4179 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);
4186 void R_UpdateAllTextureInfo(entity_render_t *ent)
4190 for (i = 0;i < ent->model->num_texturesperskin;i++)
4191 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4194 rsurfacestate_t rsurface;
4196 void R_Mesh_ResizeArrays(int newvertices)
4199 if (rsurface.array_size >= newvertices)
4201 if (rsurface.array_modelvertex3f)
4202 Mem_Free(rsurface.array_modelvertex3f);
4203 rsurface.array_size = (newvertices + 1023) & ~1023;
4204 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4205 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4206 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4207 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4208 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4209 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4210 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4211 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4212 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4213 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4214 rsurface.array_color4f = base + rsurface.array_size * 27;
4215 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4218 void RSurf_CleanUp(void)
4221 if (rsurface.mode == RSURFMODE_GLSL)
4223 qglUseProgramObjectARB(0);CHECKGLERROR
4225 GL_AlphaTest(false);
4226 rsurface.mode = RSURFMODE_NONE;
4227 rsurface.uselightmaptexture = false;
4228 rsurface.texture = NULL;
4231 void RSurf_ActiveWorldEntity(void)
4233 model_t *model = r_refdef.worldmodel;
4235 if (rsurface.array_size < model->surfmesh.num_vertices)
4236 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4237 rsurface.matrix = identitymatrix;
4238 rsurface.inversematrix = identitymatrix;
4239 R_Mesh_Matrix(&identitymatrix);
4240 VectorCopy(r_view.origin, rsurface.modelorg);
4241 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4242 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4243 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4244 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4245 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4246 rsurface.frameblend[0].frame = 0;
4247 rsurface.frameblend[0].lerp = 1;
4248 rsurface.frameblend[1].frame = 0;
4249 rsurface.frameblend[1].lerp = 0;
4250 rsurface.frameblend[2].frame = 0;
4251 rsurface.frameblend[2].lerp = 0;
4252 rsurface.frameblend[3].frame = 0;
4253 rsurface.frameblend[3].lerp = 0;
4254 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4255 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4256 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4257 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4258 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4259 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4260 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4261 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4262 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4263 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4264 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4265 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4266 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4267 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4268 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4269 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4270 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4271 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4272 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4273 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4274 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4275 rsurface.modelelement3i = model->surfmesh.data_element3i;
4276 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4277 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4278 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4279 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4280 rsurface.modelsurfaces = model->data_surfaces;
4281 rsurface.generatedvertex = false;
4282 rsurface.vertex3f = rsurface.modelvertex3f;
4283 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4284 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4285 rsurface.svector3f = rsurface.modelsvector3f;
4286 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4287 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4288 rsurface.tvector3f = rsurface.modeltvector3f;
4289 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4290 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4291 rsurface.normal3f = rsurface.modelnormal3f;
4292 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4293 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4294 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4297 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4299 model_t *model = ent->model;
4301 if (rsurface.array_size < model->surfmesh.num_vertices)
4302 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4303 rsurface.matrix = ent->matrix;
4304 rsurface.inversematrix = ent->inversematrix;
4305 R_Mesh_Matrix(&rsurface.matrix);
4306 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4307 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4308 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4309 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4310 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4311 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4312 rsurface.frameblend[0] = ent->frameblend[0];
4313 rsurface.frameblend[1] = ent->frameblend[1];
4314 rsurface.frameblend[2] = ent->frameblend[2];
4315 rsurface.frameblend[3] = ent->frameblend[3];
4316 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4320 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4321 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4322 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4323 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4324 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4326 else if (wantnormals)
4328 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4329 rsurface.modelsvector3f = NULL;
4330 rsurface.modeltvector3f = NULL;
4331 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4332 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4336 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4337 rsurface.modelsvector3f = NULL;
4338 rsurface.modeltvector3f = NULL;
4339 rsurface.modelnormal3f = NULL;
4340 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4342 rsurface.modelvertex3f_bufferobject = 0;
4343 rsurface.modelvertex3f_bufferoffset = 0;
4344 rsurface.modelsvector3f_bufferobject = 0;
4345 rsurface.modelsvector3f_bufferoffset = 0;
4346 rsurface.modeltvector3f_bufferobject = 0;
4347 rsurface.modeltvector3f_bufferoffset = 0;
4348 rsurface.modelnormal3f_bufferobject = 0;
4349 rsurface.modelnormal3f_bufferoffset = 0;
4350 rsurface.generatedvertex = true;
4354 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4355 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4356 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4357 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4358 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4359 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4360 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4361 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4362 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4363 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4364 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4365 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4366 rsurface.generatedvertex = false;
4368 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4369 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4370 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4371 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4372 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4373 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4374 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4375 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4376 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4377 rsurface.modelelement3i = model->surfmesh.data_element3i;
4378 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4379 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4380 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4381 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4382 rsurface.modelsurfaces = model->data_surfaces;
4383 rsurface.vertex3f = rsurface.modelvertex3f;
4384 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4385 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4386 rsurface.svector3f = rsurface.modelsvector3f;
4387 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4388 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4389 rsurface.tvector3f = rsurface.modeltvector3f;
4390 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4391 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4392 rsurface.normal3f = rsurface.modelnormal3f;
4393 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4394 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4395 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4398 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4399 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4402 int texturesurfaceindex;
4407 const float *v1, *in_tc;
4409 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4411 q3shaderinfo_deform_t *deform;
4412 // 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
4413 if (rsurface.generatedvertex)
4415 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4416 generatenormals = true;
4417 for (i = 0;i < Q3MAXDEFORMS;i++)
4419 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4421 generatetangents = true;
4422 generatenormals = true;
4424 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4425 generatenormals = true;
4427 if (generatenormals && !rsurface.modelnormal3f)
4429 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4430 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4431 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4432 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4434 if (generatetangents && !rsurface.modelsvector3f)
4436 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4437 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4438 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4439 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4440 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4441 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4442 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);
4445 rsurface.vertex3f = rsurface.modelvertex3f;
4446 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4447 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4448 rsurface.svector3f = rsurface.modelsvector3f;
4449 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4450 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4451 rsurface.tvector3f = rsurface.modeltvector3f;
4452 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4453 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4454 rsurface.normal3f = rsurface.modelnormal3f;
4455 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4456 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4457 // if vertices are deformed (sprite flares and things in maps, possibly
4458 // water waves, bulges and other deformations), generate them into
4459 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4460 // (may be static model data or generated data for an animated model, or
4461 // the previous deform pass)
4462 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4464 switch (deform->deform)
4467 case Q3DEFORM_PROJECTIONSHADOW:
4468 case Q3DEFORM_TEXT0:
4469 case Q3DEFORM_TEXT1:
4470 case Q3DEFORM_TEXT2:
4471 case Q3DEFORM_TEXT3:
4472 case Q3DEFORM_TEXT4:
4473 case Q3DEFORM_TEXT5:
4474 case Q3DEFORM_TEXT6:
4475 case Q3DEFORM_TEXT7:
4478 case Q3DEFORM_AUTOSPRITE:
4479 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4480 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4481 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4482 VectorNormalize(newforward);
4483 VectorNormalize(newright);
4484 VectorNormalize(newup);
4485 // make deformed versions of only the model vertices used by the specified surfaces
4486 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4488 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4489 // a single autosprite surface can contain multiple sprites...
4490 for (j = 0;j < surface->num_vertices - 3;j += 4)
4492 VectorClear(center);
4493 for (i = 0;i < 4;i++)
4494 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4495 VectorScale(center, 0.25f, center);
4496 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4497 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4498 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4499 for (i = 0;i < 4;i++)
4501 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4502 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4505 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);
4506 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);
4508 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4509 rsurface.vertex3f_bufferobject = 0;
4510 rsurface.vertex3f_bufferoffset = 0;
4511 rsurface.svector3f = rsurface.array_deformedsvector3f;
4512 rsurface.svector3f_bufferobject = 0;
4513 rsurface.svector3f_bufferoffset = 0;
4514 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4515 rsurface.tvector3f_bufferobject = 0;
4516 rsurface.tvector3f_bufferoffset = 0;
4517 rsurface.normal3f = rsurface.array_deformednormal3f;
4518 rsurface.normal3f_bufferobject = 0;
4519 rsurface.normal3f_bufferoffset = 0;
4521 case Q3DEFORM_AUTOSPRITE2:
4522 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4523 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4524 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4525 VectorNormalize(newforward);
4526 VectorNormalize(newright);
4527 VectorNormalize(newup);
4528 // make deformed versions of only the model vertices used by the specified surfaces
4529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4531 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4532 const float *v1, *v2;
4542 memset(shortest, 0, sizeof(shortest));
4543 // a single autosprite surface can contain multiple sprites...
4544 for (j = 0;j < surface->num_vertices - 3;j += 4)
4546 VectorClear(center);
4547 for (i = 0;i < 4;i++)
4548 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4549 VectorScale(center, 0.25f, center);
4550 // find the two shortest edges, then use them to define the
4551 // axis vectors for rotating around the central axis
4552 for (i = 0;i < 6;i++)
4554 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4555 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4557 Debug_PolygonBegin(NULL, 0, false, 0);
4558 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4559 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);
4560 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4563 l = VectorDistance2(v1, v2);
4564 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4566 l += (1.0f / 1024.0f);
4567 if (shortest[0].length2 > l || i == 0)
4569 shortest[1] = shortest[0];
4570 shortest[0].length2 = l;
4571 shortest[0].v1 = v1;
4572 shortest[0].v2 = v2;
4574 else if (shortest[1].length2 > l || i == 1)
4576 shortest[1].length2 = l;
4577 shortest[1].v1 = v1;
4578 shortest[1].v2 = v2;
4581 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4582 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4584 Debug_PolygonBegin(NULL, 0, false, 0);
4585 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4586 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);
4587 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4590 // this calculates the right vector from the shortest edge
4591 // and the up vector from the edge midpoints
4592 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4593 VectorNormalize(right);
4594 VectorSubtract(end, start, up);
4595 VectorNormalize(up);
4596 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4597 //VectorSubtract(rsurface.modelorg, center, forward);
4598 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4599 VectorNegate(forward, forward);
4600 VectorReflect(forward, 0, up, forward);
4601 VectorNormalize(forward);
4602 CrossProduct(up, forward, newright);
4603 VectorNormalize(newright);
4605 Debug_PolygonBegin(NULL, 0, false, 0);
4606 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);
4607 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4608 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4612 Debug_PolygonBegin(NULL, 0, false, 0);
4613 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4614 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4615 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4618 // rotate the quad around the up axis vector, this is made
4619 // especially easy by the fact we know the quad is flat,
4620 // so we only have to subtract the center position and
4621 // measure distance along the right vector, and then
4622 // multiply that by the newright vector and add back the
4624 // we also need to subtract the old position to undo the
4625 // displacement from the center, which we do with a
4626 // DotProduct, the subtraction/addition of center is also
4627 // optimized into DotProducts here
4628 l = DotProduct(right, center);
4629 for (i = 0;i < 4;i++)
4631 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4632 f = DotProduct(right, v1) - l;
4633 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4636 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);
4637 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);
4639 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4640 rsurface.vertex3f_bufferobject = 0;
4641 rsurface.vertex3f_bufferoffset = 0;
4642 rsurface.svector3f = rsurface.array_deformedsvector3f;
4643 rsurface.svector3f_bufferobject = 0;
4644 rsurface.svector3f_bufferoffset = 0;
4645 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4646 rsurface.tvector3f_bufferobject = 0;
4647 rsurface.tvector3f_bufferoffset = 0;
4648 rsurface.normal3f = rsurface.array_deformednormal3f;
4649 rsurface.normal3f_bufferobject = 0;
4650 rsurface.normal3f_bufferoffset = 0;
4652 case Q3DEFORM_NORMAL:
4653 // deform the normals to make reflections wavey
4654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4656 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4657 for (j = 0;j < surface->num_vertices;j++)
4660 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4661 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4662 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4663 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4664 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4665 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4666 VectorNormalize(normal);
4668 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);
4670 rsurface.svector3f = rsurface.array_deformedsvector3f;
4671 rsurface.svector3f_bufferobject = 0;
4672 rsurface.svector3f_bufferoffset = 0;
4673 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4674 rsurface.tvector3f_bufferobject = 0;
4675 rsurface.tvector3f_bufferoffset = 0;
4676 rsurface.normal3f = rsurface.array_deformednormal3f;
4677 rsurface.normal3f_bufferobject = 0;
4678 rsurface.normal3f_bufferoffset = 0;
4681 // deform vertex array to make wavey water and flags and such
4682 waveparms[0] = deform->waveparms[0];
4683 waveparms[1] = deform->waveparms[1];
4684 waveparms[2] = deform->waveparms[2];
4685 waveparms[3] = deform->waveparms[3];
4686 // this is how a divisor of vertex influence on deformation
4687 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4688 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4689 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4691 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4692 for (j = 0;j < surface->num_vertices;j++)
4694 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4695 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4696 // if the wavefunc depends on time, evaluate it per-vertex
4699 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4700 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4702 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4705 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4706 rsurface.vertex3f_bufferobject = 0;
4707 rsurface.vertex3f_bufferoffset = 0;
4709 case Q3DEFORM_BULGE:
4710 // deform vertex array to make the surface have moving bulges
4711 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4713 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4714 for (j = 0;j < surface->num_vertices;j++)
4716 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4717 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4720 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4721 rsurface.vertex3f_bufferobject = 0;
4722 rsurface.vertex3f_bufferoffset = 0;
4725 // deform vertex array
4726 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4727 VectorScale(deform->parms, scale, waveparms);
4728 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4731 for (j = 0;j < surface->num_vertices;j++)
4732 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4734 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4735 rsurface.vertex3f_bufferobject = 0;
4736 rsurface.vertex3f_bufferoffset = 0;
4740 // generate texcoords based on the chosen texcoord source
4741 switch(rsurface.texture->tcgen.tcgen)
4744 case Q3TCGEN_TEXTURE:
4745 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4746 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4747 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4749 case Q3TCGEN_LIGHTMAP:
4750 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4751 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4752 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4754 case Q3TCGEN_VECTOR:
4755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4758 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)
4760 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4761 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4764 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4765 rsurface.texcoordtexture2f_bufferobject = 0;
4766 rsurface.texcoordtexture2f_bufferoffset = 0;
4768 case Q3TCGEN_ENVIRONMENT:
4769 // make environment reflections using a spheremap
4770 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4772 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4773 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4774 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4775 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4776 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4778 float l, d, eyedir[3];
4779 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4780 l = 0.5f / VectorLength(eyedir);
4781 d = DotProduct(normal, eyedir)*2;
4782 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4783 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4786 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4787 rsurface.texcoordtexture2f_bufferobject = 0;
4788 rsurface.texcoordtexture2f_bufferoffset = 0;
4791 // the only tcmod that needs software vertex processing is turbulent, so
4792 // check for it here and apply the changes if needed
4793 // and we only support that as the first one
4794 // (handling a mixture of turbulent and other tcmods would be problematic
4795 // without punting it entirely to a software path)
4796 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4798 amplitude = rsurface.texture->tcmods[0].parms[1];
4799 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4800 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4803 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)
4805 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4806 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4809 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4810 rsurface.texcoordtexture2f_bufferobject = 0;
4811 rsurface.texcoordtexture2f_bufferoffset = 0;
4813 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4814 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4815 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4816 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4819 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4822 const msurface_t *surface = texturesurfacelist[0];
4823 const msurface_t *surface2;
4828 // TODO: lock all array ranges before render, rather than on each surface
4829 if (texturenumsurfaces == 1)
4831 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4832 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));
4834 else if (r_batchmode.integer == 2)
4836 #define MAXBATCHTRIANGLES 4096
4837 int batchtriangles = 0;
4838 int batchelements[MAXBATCHTRIANGLES*3];
4839 for (i = 0;i < texturenumsurfaces;i = j)
4841 surface = texturesurfacelist[i];
4843 if (surface->num_triangles > MAXBATCHTRIANGLES)
4845 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));
4848 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4849 batchtriangles = surface->num_triangles;
4850 firstvertex = surface->num_firstvertex;
4851 endvertex = surface->num_firstvertex + surface->num_vertices;
4852 for (;j < texturenumsurfaces;j++)
4854 surface2 = texturesurfacelist[j];
4855 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4857 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4858 batchtriangles += surface2->num_triangles;
4859 firstvertex = min(firstvertex, surface2->num_firstvertex);
4860 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4862 surface2 = texturesurfacelist[j-1];
4863 numvertices = endvertex - firstvertex;
4864 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4867 else if (r_batchmode.integer == 1)
4869 for (i = 0;i < texturenumsurfaces;i = j)
4871 surface = texturesurfacelist[i];
4872 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4873 if (texturesurfacelist[j] != surface2)
4875 surface2 = texturesurfacelist[j-1];
4876 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4877 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4878 GL_LockArrays(surface->num_firstvertex, numvertices);
4879 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4884 for (i = 0;i < texturenumsurfaces;i++)
4886 surface = texturesurfacelist[i];
4887 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4888 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));
4893 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4895 int i, planeindex, vertexindex;
4899 r_waterstate_waterplane_t *p, *bestp;
4900 msurface_t *surface;
4901 if (r_waterstate.renderingscene)
4903 for (i = 0;i < texturenumsurfaces;i++)
4905 surface = texturesurfacelist[i];
4906 if (lightmaptexunit >= 0)
4907 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4908 if (deluxemaptexunit >= 0)
4909 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4910 // pick the closest matching water plane
4913 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4916 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4918 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4919 d += fabs(PlaneDiff(vert, &p->plane));
4921 if (bestd > d || !bestp)
4929 if (refractiontexunit >= 0)
4930 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4931 if (reflectiontexunit >= 0)
4932 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4936 if (refractiontexunit >= 0)
4937 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4938 if (reflectiontexunit >= 0)
4939 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4941 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4942 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));
4946 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4950 const msurface_t *surface = texturesurfacelist[0];
4951 const msurface_t *surface2;
4956 // TODO: lock all array ranges before render, rather than on each surface
4957 if (texturenumsurfaces == 1)
4959 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4960 if (deluxemaptexunit >= 0)
4961 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4962 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4963 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));
4965 else if (r_batchmode.integer == 2)
4967 #define MAXBATCHTRIANGLES 4096
4968 int batchtriangles = 0;
4969 int batchelements[MAXBATCHTRIANGLES*3];
4970 for (i = 0;i < texturenumsurfaces;i = j)
4972 surface = texturesurfacelist[i];
4973 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4974 if (deluxemaptexunit >= 0)
4975 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4977 if (surface->num_triangles > MAXBATCHTRIANGLES)
4979 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));
4982 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4983 batchtriangles = surface->num_triangles;
4984 firstvertex = surface->num_firstvertex;
4985 endvertex = surface->num_firstvertex + surface->num_vertices;
4986 for (;j < texturenumsurfaces;j++)
4988 surface2 = texturesurfacelist[j];
4989 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4991 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4992 batchtriangles += surface2->num_triangles;
4993 firstvertex = min(firstvertex, surface2->num_firstvertex);
4994 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4996 surface2 = texturesurfacelist[j-1];
4997 numvertices = endvertex - firstvertex;
4998 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5001 else if (r_batchmode.integer == 1)
5004 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5005 for (i = 0;i < texturenumsurfaces;i = j)
5007 surface = texturesurfacelist[i];
5008 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5009 if (texturesurfacelist[j] != surface2)
5011 Con_Printf(" %i", j - i);
5014 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5016 for (i = 0;i < texturenumsurfaces;i = j)
5018 surface = texturesurfacelist[i];
5019 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5020 if (deluxemaptexunit >= 0)
5021 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5022 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5023 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5026 Con_Printf(" %i", j - i);
5028 surface2 = texturesurfacelist[j-1];
5029 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5030 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5031 GL_LockArrays(surface->num_firstvertex, numvertices);
5032 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5040 for (i = 0;i < texturenumsurfaces;i++)
5042 surface = texturesurfacelist[i];
5043 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5044 if (deluxemaptexunit >= 0)
5045 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5046 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5047 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));
5052 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5055 int texturesurfaceindex;
5056 if (r_showsurfaces.integer == 2)
5058 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5060 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5061 for (j = 0;j < surface->num_triangles;j++)
5063 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5064 GL_Color(f, f, f, 1);
5065 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)));
5071 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5073 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5074 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5075 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);
5076 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5077 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));
5082 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5084 int texturesurfaceindex;
5088 if (rsurface.lightmapcolor4f)
5090 // generate color arrays for the surfaces in this list
5091 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5093 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5094 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)
5096 f = FogPoint_Model(v);
5106 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5108 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5109 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)
5111 f = FogPoint_Model(v);
5119 rsurface.lightmapcolor4f = rsurface.array_color4f;
5120 rsurface.lightmapcolor4f_bufferobject = 0;
5121 rsurface.lightmapcolor4f_bufferoffset = 0;
5124 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5126 int texturesurfaceindex;
5129 if (!rsurface.lightmapcolor4f)
5131 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5133 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5134 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)
5142 rsurface.lightmapcolor4f = rsurface.array_color4f;
5143 rsurface.lightmapcolor4f_bufferobject = 0;
5144 rsurface.lightmapcolor4f_bufferoffset = 0;
5147 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5150 rsurface.lightmapcolor4f = NULL;
5151 rsurface.lightmapcolor4f_bufferobject = 0;
5152 rsurface.lightmapcolor4f_bufferoffset = 0;
5153 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5154 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5155 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5156 GL_Color(r, g, b, a);
5157 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5160 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5162 // TODO: optimize applyfog && applycolor case
5163 // just apply fog if necessary, and tint the fog color array if necessary
5164 rsurface.lightmapcolor4f = NULL;
5165 rsurface.lightmapcolor4f_bufferobject = 0;
5166 rsurface.lightmapcolor4f_bufferoffset = 0;
5167 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5168 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5169 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5170 GL_Color(r, g, b, a);
5171 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5174 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5176 int texturesurfaceindex;
5180 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5182 // generate color arrays for the surfaces in this list
5183 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5185 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5186 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5188 if (surface->lightmapinfo->samples)
5190 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5191 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5192 VectorScale(lm, scale, c);
5193 if (surface->lightmapinfo->styles[1] != 255)
5195 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5197 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5198 VectorMA(c, scale, lm, c);
5199 if (surface->lightmapinfo->styles[2] != 255)
5202 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5203 VectorMA(c, scale, lm, c);
5204 if (surface->lightmapinfo->styles[3] != 255)
5207 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5208 VectorMA(c, scale, lm, c);
5218 rsurface.lightmapcolor4f = rsurface.array_color4f;
5219 rsurface.lightmapcolor4f_bufferobject = 0;
5220 rsurface.lightmapcolor4f_bufferoffset = 0;
5224 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5225 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5226 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5228 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5229 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5230 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5231 GL_Color(r, g, b, a);
5232 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5235 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5237 int texturesurfaceindex;
5241 vec3_t ambientcolor;
5242 vec3_t diffusecolor;
5246 VectorCopy(rsurface.modellight_lightdir, lightdir);
5247 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5248 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5249 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5250 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5251 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5252 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5253 if (VectorLength2(diffusecolor) > 0)
5255 // generate color arrays for the surfaces in this list
5256 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5258 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5259 int numverts = surface->num_vertices;
5260 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5261 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5262 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5263 // q3-style directional shading
5264 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5266 if ((f = DotProduct(c2, lightdir)) > 0)
5267 VectorMA(ambientcolor, f, diffusecolor, c);
5269 VectorCopy(ambientcolor, c);
5278 rsurface.lightmapcolor4f = rsurface.array_color4f;
5279 rsurface.lightmapcolor4f_bufferobject = 0;
5280 rsurface.lightmapcolor4f_bufferoffset = 0;
5284 r = ambientcolor[0];
5285 g = ambientcolor[1];
5286 b = ambientcolor[2];
5287 rsurface.lightmapcolor4f = NULL;
5288 rsurface.lightmapcolor4f_bufferobject = 0;
5289 rsurface.lightmapcolor4f_bufferoffset = 0;
5291 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5292 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5293 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5294 GL_Color(r, g, b, a);
5295 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5298 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5300 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5301 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5302 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5303 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5304 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5306 rsurface.mode = RSURFMODE_SHOWSURFACES;
5308 GL_BlendFunc(GL_ONE, GL_ZERO);
5309 R_Mesh_ColorPointer(NULL, 0, 0);
5310 R_Mesh_ResetTextureState();
5312 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5313 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5316 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5318 // transparent sky would be ridiculous
5319 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5321 if (rsurface.mode != RSURFMODE_SKY)
5323 if (rsurface.mode == RSURFMODE_GLSL)
5325 qglUseProgramObjectARB(0);CHECKGLERROR
5327 rsurface.mode = RSURFMODE_SKY;
5331 skyrendernow = false;
5333 // restore entity matrix
5334 R_Mesh_Matrix(&rsurface.matrix);
5336 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5337 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5338 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5339 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5341 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5342 // skymasking on them, and Quake3 never did sky masking (unlike
5343 // software Quake and software Quake2), so disable the sky masking
5344 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5345 // and skymasking also looks very bad when noclipping outside the
5346 // level, so don't use it then either.
5347 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5349 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5350 R_Mesh_ColorPointer(NULL, 0, 0);
5351 R_Mesh_ResetTextureState();
5352 if (skyrendermasked)
5354 // depth-only (masking)
5355 GL_ColorMask(0,0,0,0);
5356 // just to make sure that braindead drivers don't draw
5357 // anything despite that colormask...
5358 GL_BlendFunc(GL_ZERO, GL_ONE);
5363 GL_BlendFunc(GL_ONE, GL_ZERO);
5365 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5366 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5367 if (skyrendermasked)
5368 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5372 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5374 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5377 if (rsurface.mode != RSURFMODE_GLSL)
5379 rsurface.mode = RSURFMODE_GLSL;
5380 R_Mesh_ResetTextureState();
5383 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5384 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5385 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5386 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5387 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5388 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5389 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5392 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5393 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5394 R_Mesh_ColorPointer(NULL, 0, 0);
5396 else if (rsurface.uselightmaptexture)
5398 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5399 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5400 R_Mesh_ColorPointer(NULL, 0, 0);
5404 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5405 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5406 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5408 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5409 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5410 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5412 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5414 // render background
5415 GL_BlendFunc(GL_ONE, GL_ZERO);
5417 GL_AlphaTest(false);
5419 GL_Color(1, 1, 1, 1);
5420 R_Mesh_ColorPointer(NULL, 0, 0);
5422 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5423 if (r_glsl_permutation)
5425 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5426 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5427 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5428 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5429 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5430 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5431 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5434 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5435 GL_DepthMask(false);
5436 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5439 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5440 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5441 R_Mesh_ColorPointer(NULL, 0, 0);
5443 else if (rsurface.uselightmaptexture)
5445 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5446 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5447 R_Mesh_ColorPointer(NULL, 0, 0);
5451 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5452 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5453 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5455 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5456 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5459 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5460 if (!r_glsl_permutation)
5463 if (rsurface.lightmode == 2)
5464 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5466 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5467 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5468 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5469 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5470 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5471 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5472 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]);
5474 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5476 GL_BlendFunc(GL_ONE, GL_ZERO);
5478 GL_AlphaTest(false);
5481 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5483 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5484 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5486 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5490 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5491 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5493 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5495 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5500 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5502 // OpenGL 1.3 path - anything not completely ancient
5503 int texturesurfaceindex;
5504 qboolean applycolor;
5508 const texturelayer_t *layer;
5509 if (rsurface.mode != RSURFMODE_MULTIPASS)
5510 rsurface.mode = RSURFMODE_MULTIPASS;
5511 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5513 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5516 int layertexrgbscale;
5517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5519 if (layerindex == 0)
5523 GL_AlphaTest(false);
5524 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5527 GL_DepthMask(layer->depthmask);
5528 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5529 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5531 layertexrgbscale = 4;
5532 VectorScale(layer->color, 0.25f, layercolor);
5534 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5536 layertexrgbscale = 2;
5537 VectorScale(layer->color, 0.5f, layercolor);
5541 layertexrgbscale = 1;
5542 VectorScale(layer->color, 1.0f, layercolor);
5544 layercolor[3] = layer->color[3];
5545 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5546 R_Mesh_ColorPointer(NULL, 0, 0);
5547 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5548 switch (layer->type)
5550 case TEXTURELAYERTYPE_LITTEXTURE:
5551 memset(&m, 0, sizeof(m));
5552 m.tex[0] = R_GetTexture(r_texture_white);
5553 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5554 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5555 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5556 m.tex[1] = R_GetTexture(layer->texture);
5557 m.texmatrix[1] = layer->texmatrix;
5558 m.texrgbscale[1] = layertexrgbscale;
5559 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5560 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5561 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5562 R_Mesh_TextureState(&m);
5563 if (rsurface.lightmode == 2)
5564 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5565 else if (rsurface.uselightmaptexture)
5566 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5568 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5570 case TEXTURELAYERTYPE_TEXTURE:
5571 memset(&m, 0, sizeof(m));
5572 m.tex[0] = R_GetTexture(layer->texture);
5573 m.texmatrix[0] = layer->texmatrix;
5574 m.texrgbscale[0] = layertexrgbscale;
5575 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5576 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5577 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5578 R_Mesh_TextureState(&m);
5579 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5581 case TEXTURELAYERTYPE_FOG:
5582 memset(&m, 0, sizeof(m));
5583 m.texrgbscale[0] = layertexrgbscale;
5586 m.tex[0] = R_GetTexture(layer->texture);
5587 m.texmatrix[0] = layer->texmatrix;
5588 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5589 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5590 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5592 R_Mesh_TextureState(&m);
5593 // generate a color array for the fog pass
5594 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5595 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5599 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5600 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)
5602 f = 1 - FogPoint_Model(v);
5603 c[0] = layercolor[0];
5604 c[1] = layercolor[1];
5605 c[2] = layercolor[2];
5606 c[3] = f * layercolor[3];
5609 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5612 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5614 GL_LockArrays(0, 0);
5617 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5619 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5620 GL_AlphaTest(false);
5624 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5626 // OpenGL 1.1 - crusty old voodoo path
5627 int texturesurfaceindex;
5631 const texturelayer_t *layer;
5632 if (rsurface.mode != RSURFMODE_MULTIPASS)
5633 rsurface.mode = RSURFMODE_MULTIPASS;
5634 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5636 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5640 if (layerindex == 0)
5644 GL_AlphaTest(false);
5645 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5648 GL_DepthMask(layer->depthmask);
5649 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5650 R_Mesh_ColorPointer(NULL, 0, 0);
5651 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5652 switch (layer->type)
5654 case TEXTURELAYERTYPE_LITTEXTURE:
5655 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5657 // two-pass lit texture with 2x rgbscale
5658 // first the lightmap pass
5659 memset(&m, 0, sizeof(m));
5660 m.tex[0] = R_GetTexture(r_texture_white);
5661 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5662 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5663 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5664 R_Mesh_TextureState(&m);
5665 if (rsurface.lightmode == 2)
5666 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5667 else if (rsurface.uselightmaptexture)
5668 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5670 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5671 GL_LockArrays(0, 0);
5672 // then apply the texture to it
5673 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5674 memset(&m, 0, sizeof(m));
5675 m.tex[0] = R_GetTexture(layer->texture);
5676 m.texmatrix[0] = layer->texmatrix;
5677 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5678 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5679 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5680 R_Mesh_TextureState(&m);
5681 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);
5685 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5686 memset(&m, 0, sizeof(m));
5687 m.tex[0] = R_GetTexture(layer->texture);
5688 m.texmatrix[0] = layer->texmatrix;
5689 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5690 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5691 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5692 R_Mesh_TextureState(&m);
5693 if (rsurface.lightmode == 2)
5694 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);
5696 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);
5699 case TEXTURELAYERTYPE_TEXTURE:
5700 // singletexture unlit texture with transparency support
5701 memset(&m, 0, sizeof(m));
5702 m.tex[0] = R_GetTexture(layer->texture);
5703 m.texmatrix[0] = layer->texmatrix;
5704 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5705 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5706 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5707 R_Mesh_TextureState(&m);
5708 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);
5710 case TEXTURELAYERTYPE_FOG:
5711 // singletexture fogging
5712 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5715 memset(&m, 0, sizeof(m));
5716 m.tex[0] = R_GetTexture(layer->texture);
5717 m.texmatrix[0] = layer->texmatrix;
5718 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5719 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5720 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5721 R_Mesh_TextureState(&m);
5724 R_Mesh_ResetTextureState();
5725 // generate a color array for the fog pass
5726 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5731 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)
5733 f = 1 - FogPoint_Model(v);
5734 c[0] = layer->color[0];
5735 c[1] = layer->color[1];
5736 c[2] = layer->color[2];
5737 c[3] = f * layer->color[3];
5740 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5743 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5745 GL_LockArrays(0, 0);
5748 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5750 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5751 GL_AlphaTest(false);
5755 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5757 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5759 rsurface.rtlight = NULL;
5763 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5765 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5767 if (rsurface.mode != RSURFMODE_MULTIPASS)
5768 rsurface.mode = RSURFMODE_MULTIPASS;
5769 if (r_depthfirst.integer == 3)
5771 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5772 if (!r_view.showdebug)
5773 GL_Color(0, 0, 0, 1);
5775 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5779 GL_ColorMask(0,0,0,0);
5782 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5783 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5784 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5786 GL_BlendFunc(GL_ONE, GL_ZERO);
5788 GL_AlphaTest(false);
5789 R_Mesh_ColorPointer(NULL, 0, 0);
5790 R_Mesh_ResetTextureState();
5791 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5792 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5793 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5794 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5796 else if (r_depthfirst.integer == 3)
5798 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5800 GL_Color(0, 0, 0, 1);
5801 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5803 else if (r_showsurfaces.integer)
5805 if (rsurface.mode != RSURFMODE_MULTIPASS)
5806 rsurface.mode = RSURFMODE_MULTIPASS;
5807 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5808 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5810 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5811 GL_BlendFunc(GL_ONE, GL_ZERO);
5812 GL_DepthMask(writedepth);
5814 GL_AlphaTest(false);
5815 R_Mesh_ColorPointer(NULL, 0, 0);
5816 R_Mesh_ResetTextureState();
5817 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5818 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5819 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5821 else if (gl_lightmaps.integer)
5824 if (rsurface.mode != RSURFMODE_MULTIPASS)
5825 rsurface.mode = RSURFMODE_MULTIPASS;
5826 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5828 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5829 GL_BlendFunc(GL_ONE, GL_ZERO);
5830 GL_DepthMask(writedepth);
5832 GL_AlphaTest(false);
5833 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5834 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5835 R_Mesh_ColorPointer(NULL, 0, 0);
5836 memset(&m, 0, sizeof(m));
5837 m.tex[0] = R_GetTexture(r_texture_white);
5838 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5839 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5840 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5841 R_Mesh_TextureState(&m);
5842 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5843 if (rsurface.lightmode == 2)
5844 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5845 else if (rsurface.uselightmaptexture)
5846 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5848 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5849 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5851 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5853 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5854 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5856 else if (rsurface.texture->currentnumlayers)
5858 // write depth for anything we skipped on the depth-only pass earlier
5859 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5861 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5862 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5863 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5864 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5865 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5866 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5867 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5868 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5869 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5870 if (r_glsl.integer && gl_support_fragment_shader)
5871 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5872 else if (gl_combine.integer && r_textureunits.integer >= 2)
5873 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5875 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5876 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5879 GL_LockArrays(0, 0);
5882 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5885 int texturenumsurfaces, endsurface;
5887 msurface_t *surface;
5888 msurface_t *texturesurfacelist[1024];
5890 // if the model is static it doesn't matter what value we give for
5891 // wantnormals and wanttangents, so this logic uses only rules applicable
5892 // to a model, knowing that they are meaningless otherwise
5893 if (ent == r_refdef.worldentity)
5894 RSurf_ActiveWorldEntity();
5895 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5896 RSurf_ActiveModelEntity(ent, false, false);
5898 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5900 for (i = 0;i < numsurfaces;i = j)
5903 surface = rsurface.modelsurfaces + surfacelist[i];
5904 texture = surface->texture;
5905 R_UpdateTextureInfo(ent, texture);
5906 rsurface.texture = texture->currentframe;
5907 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5908 // scan ahead until we find a different texture
5909 endsurface = min(i + 1024, numsurfaces);
5910 texturenumsurfaces = 0;
5911 texturesurfacelist[texturenumsurfaces++] = surface;
5912 for (;j < endsurface;j++)
5914 surface = rsurface.modelsurfaces + surfacelist[j];
5915 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5917 texturesurfacelist[texturenumsurfaces++] = surface;
5919 // render the range of surfaces
5920 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5926 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5929 vec3_t tempcenter, center;
5931 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5934 for (i = 0;i < numsurfaces;i++)
5935 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5936 R_Water_AddWaterPlane(surfacelist[i]);
5939 // break the surface list down into batches by texture and use of lightmapping
5940 for (i = 0;i < numsurfaces;i = j)
5943 // texture is the base texture pointer, rsurface.texture is the
5944 // current frame/skin the texture is directing us to use (for example
5945 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5946 // use skin 1 instead)
5947 texture = surfacelist[i]->texture;
5948 rsurface.texture = texture->currentframe;
5949 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5950 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5952 // if this texture is not the kind we want, skip ahead to the next one
5953 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5957 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5959 // transparent surfaces get pushed off into the transparent queue
5960 const msurface_t *surface = surfacelist[i];
5963 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5964 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5965 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5966 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5967 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5971 // simply scan ahead until we find a different texture or lightmap state
5972 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5974 // render the range of surfaces
5975 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5980 float locboxvertex3f[6*4*3] =
5982 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5983 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5984 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5985 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5986 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5987 1,0,0, 0,0,0, 0,1,0, 1,1,0
5990 int locboxelement3i[6*2*3] =
6000 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6003 cl_locnode_t *loc = (cl_locnode_t *)ent;
6005 float vertex3f[6*4*3];
6007 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6008 GL_DepthMask(false);
6009 GL_DepthRange(0, 1);
6010 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6012 GL_CullFace(GL_NONE);
6013 R_Mesh_Matrix(&identitymatrix);
6015 R_Mesh_VertexPointer(vertex3f, 0, 0);
6016 R_Mesh_ColorPointer(NULL, 0, 0);
6017 R_Mesh_ResetTextureState();
6020 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6021 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6022 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6023 surfacelist[0] < 0 ? 0.5f : 0.125f);
6025 if (VectorCompare(loc->mins, loc->maxs))
6027 VectorSet(size, 2, 2, 2);
6028 VectorMA(loc->mins, -0.5f, size, mins);
6032 VectorCopy(loc->mins, mins);
6033 VectorSubtract(loc->maxs, loc->mins, size);
6036 for (i = 0;i < 6*4*3;)
6037 for (j = 0;j < 3;j++, i++)
6038 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6040 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6043 void R_DrawLocs(void)
6046 cl_locnode_t *loc, *nearestloc;
6048 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6049 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6051 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6052 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6056 void R_DrawDebugModel(entity_render_t *ent)
6058 int i, j, k, l, flagsmask;
6059 const int *elements;
6061 msurface_t *surface;
6062 model_t *model = ent->model;
6065 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6067 R_Mesh_ColorPointer(NULL, 0, 0);
6068 R_Mesh_ResetTextureState();
6069 GL_DepthRange(0, 1);
6070 GL_DepthTest(!r_showdisabledepthtest.integer);
6071 GL_DepthMask(false);
6072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6074 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6076 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6077 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6079 if (brush->colbrushf && brush->colbrushf->numtriangles)
6081 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6082 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);
6083 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6086 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6088 if (surface->num_collisiontriangles)
6090 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6091 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);
6092 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6097 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6099 if (r_showtris.integer || r_shownormals.integer)
6101 if (r_showdisabledepthtest.integer)
6103 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6104 GL_DepthMask(false);
6108 GL_BlendFunc(GL_ONE, GL_ZERO);
6111 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6113 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6115 rsurface.texture = surface->texture->currentframe;
6116 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6118 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6119 if (r_showtris.value > 0)
6121 if (!rsurface.texture->currentlayers->depthmask)
6122 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6123 else if (ent == r_refdef.worldentity)
6124 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6126 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6127 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6130 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6132 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6133 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6134 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6135 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6140 if (r_shownormals.value > 0)
6142 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6144 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6146 VectorCopy(rsurface.vertex3f + l * 3, v);
6147 qglVertex3f(v[0], v[1], v[2]);
6148 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6149 qglVertex3f(v[0], v[1], v[2]);
6153 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6155 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6157 VectorCopy(rsurface.vertex3f + l * 3, v);
6158 qglVertex3f(v[0], v[1], v[2]);
6159 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6160 qglVertex3f(v[0], v[1], v[2]);
6164 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6166 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6168 VectorCopy(rsurface.vertex3f + l * 3, v);
6169 qglVertex3f(v[0], v[1], v[2]);
6170 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6171 qglVertex3f(v[0], v[1], v[2]);
6178 rsurface.texture = NULL;
6182 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6183 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6185 int i, j, endj, f, flagsmask;
6186 int counttriangles = 0;
6187 msurface_t *surface, **surfacechain;
6189 model_t *model = r_refdef.worldmodel;
6190 const int maxsurfacelist = 1024;
6191 int numsurfacelist = 0;
6192 msurface_t *surfacelist[1024];
6196 RSurf_ActiveWorldEntity();
6198 // update light styles
6199 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6201 for (i = 0;i < model->brushq1.light_styles;i++)
6203 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6205 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6206 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6207 for (;(surface = *surfacechain);surfacechain++)
6208 surface->cached_dlight = true;
6213 R_UpdateAllTextureInfo(r_refdef.worldentity);
6214 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6218 R_DrawDebugModel(r_refdef.worldentity);
6224 rsurface.uselightmaptexture = false;
6225 rsurface.texture = NULL;
6227 j = model->firstmodelsurface;
6228 endj = j + model->nummodelsurfaces;
6231 // quickly skip over non-visible surfaces
6232 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6234 // quickly iterate over visible surfaces
6235 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6237 // process this surface
6238 surface = model->data_surfaces + j;
6239 // if this surface fits the criteria, add it to the list
6240 if (surface->num_triangles)
6242 // if lightmap parameters changed, rebuild lightmap texture
6243 if (surface->cached_dlight)
6244 R_BuildLightMap(r_refdef.worldentity, surface);
6245 // add face to draw list
6246 surfacelist[numsurfacelist++] = surface;
6247 counttriangles += surface->num_triangles;
6248 if (numsurfacelist >= maxsurfacelist)
6250 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6257 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6258 r_refdef.stats.entities_triangles += counttriangles;
6262 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6264 int i, f, flagsmask;
6265 int counttriangles = 0;
6266 msurface_t *surface, *endsurface, **surfacechain;
6268 model_t *model = ent->model;
6269 const int maxsurfacelist = 1024;
6270 int numsurfacelist = 0;
6271 msurface_t *surfacelist[1024];
6275 // if the model is static it doesn't matter what value we give for
6276 // wantnormals and wanttangents, so this logic uses only rules applicable
6277 // to a model, knowing that they are meaningless otherwise
6278 if (ent == r_refdef.worldentity)
6279 RSurf_ActiveWorldEntity();
6280 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6281 RSurf_ActiveModelEntity(ent, false, false);
6283 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6285 // update light styles
6286 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6288 for (i = 0;i < model->brushq1.light_styles;i++)
6290 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6292 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6293 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6294 for (;(surface = *surfacechain);surfacechain++)
6295 surface->cached_dlight = true;
6300 R_UpdateAllTextureInfo(ent);
6301 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6305 R_DrawDebugModel(ent);
6311 rsurface.uselightmaptexture = false;
6312 rsurface.texture = NULL;
6314 surface = model->data_surfaces + model->firstmodelsurface;
6315 endsurface = surface + model->nummodelsurfaces;
6316 for (;surface < endsurface;surface++)
6318 // if this surface fits the criteria, add it to the list
6319 if (surface->num_triangles)
6321 // if lightmap parameters changed, rebuild lightmap texture
6322 if (surface->cached_dlight)
6323 R_BuildLightMap(ent, surface);
6324 // add face to draw list
6325 surfacelist[numsurfacelist++] = surface;
6326 counttriangles += surface->num_triangles;
6327 if (numsurfacelist >= maxsurfacelist)
6329 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6335 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6336 r_refdef.stats.entities_triangles += counttriangles;