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);
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)) != 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)) != 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)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1598 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1599 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1600 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
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();
2767 R_RenderScene(false);
2769 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2770 GL_ActiveTexture(0);
2772 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2774 R_ResetViewRendering3D();
2778 r_view = originalview;
2779 r_waterstate.renderingscene = false;
2783 r_view = originalview;
2784 r_waterstate.renderingscene = false;
2785 Cvar_SetValueQuick(&r_water, 0);
2786 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2790 void R_Bloom_StartFrame(void)
2792 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2794 // set bloomwidth and bloomheight to the bloom resolution that will be
2795 // used (often less than the screen resolution for faster rendering)
2796 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2797 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2798 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2800 // calculate desired texture sizes
2801 if (gl_support_arb_texture_non_power_of_two)
2803 screentexturewidth = r_view.width;
2804 screentextureheight = r_view.height;
2805 bloomtexturewidth = r_bloomstate.bloomwidth;
2806 bloomtextureheight = r_bloomstate.bloomheight;
2810 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2811 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2812 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2813 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2818 screentexturewidth = screentextureheight = 0;
2820 else if (r_bloom.integer)
2825 screentexturewidth = screentextureheight = 0;
2826 bloomtexturewidth = bloomtextureheight = 0;
2829 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)
2831 // can't use bloom if the parameters are too weird
2832 // can't use bloom if the card does not support the texture size
2833 if (r_bloomstate.texture_screen)
2834 R_FreeTexture(r_bloomstate.texture_screen);
2835 if (r_bloomstate.texture_bloom)
2836 R_FreeTexture(r_bloomstate.texture_bloom);
2837 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2841 r_bloomstate.enabled = true;
2842 r_bloomstate.hdr = r_hdr.integer != 0;
2844 // allocate textures as needed
2845 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2847 if (r_bloomstate.texture_screen)
2848 R_FreeTexture(r_bloomstate.texture_screen);
2849 r_bloomstate.texture_screen = NULL;
2850 r_bloomstate.screentexturewidth = screentexturewidth;
2851 r_bloomstate.screentextureheight = screentextureheight;
2852 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2853 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);
2855 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2857 if (r_bloomstate.texture_bloom)
2858 R_FreeTexture(r_bloomstate.texture_bloom);
2859 r_bloomstate.texture_bloom = NULL;
2860 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2861 r_bloomstate.bloomtextureheight = bloomtextureheight;
2862 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2863 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);
2866 // set up a texcoord array for the full resolution screen image
2867 // (we have to keep this around to copy back during final render)
2868 r_bloomstate.screentexcoord2f[0] = 0;
2869 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2870 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2871 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2872 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2873 r_bloomstate.screentexcoord2f[5] = 0;
2874 r_bloomstate.screentexcoord2f[6] = 0;
2875 r_bloomstate.screentexcoord2f[7] = 0;
2877 // set up a texcoord array for the reduced resolution bloom image
2878 // (which will be additive blended over the screen image)
2879 r_bloomstate.bloomtexcoord2f[0] = 0;
2880 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2881 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2882 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2883 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2884 r_bloomstate.bloomtexcoord2f[5] = 0;
2885 r_bloomstate.bloomtexcoord2f[6] = 0;
2886 r_bloomstate.bloomtexcoord2f[7] = 0;
2889 void R_Bloom_CopyScreenTexture(float colorscale)
2891 r_refdef.stats.bloom++;
2893 R_ResetViewRendering2D();
2894 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2895 R_Mesh_ColorPointer(NULL, 0, 0);
2896 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2897 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2899 // copy view into the screen texture
2900 GL_ActiveTexture(0);
2902 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
2903 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2905 // now scale it down to the bloom texture size
2907 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2908 GL_BlendFunc(GL_ONE, GL_ZERO);
2909 GL_Color(colorscale, colorscale, colorscale, 1);
2910 // TODO: optimize with multitexture or GLSL
2911 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2912 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2914 // we now have a bloom image in the framebuffer
2915 // copy it into the bloom image texture for later processing
2916 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2917 GL_ActiveTexture(0);
2919 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
2920 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2923 void R_Bloom_CopyHDRTexture(void)
2925 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2926 GL_ActiveTexture(0);
2928 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
2929 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2932 void R_Bloom_MakeTexture(void)
2935 float xoffset, yoffset, r, brighten;
2937 r_refdef.stats.bloom++;
2939 R_ResetViewRendering2D();
2940 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2941 R_Mesh_ColorPointer(NULL, 0, 0);
2943 // we have a bloom image in the framebuffer
2945 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2947 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2950 r = bound(0, r_bloom_colorexponent.value / x, 1);
2951 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2952 GL_Color(r, r, r, 1);
2953 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2954 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2955 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2956 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2958 // copy the vertically blurred bloom view to a texture
2959 GL_ActiveTexture(0);
2961 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
2962 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2965 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2966 brighten = r_bloom_brighten.value;
2968 brighten *= r_hdr_range.value;
2969 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2970 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2972 for (dir = 0;dir < 2;dir++)
2974 // blend on at multiple vertical offsets to achieve a vertical blur
2975 // TODO: do offset blends using GLSL
2976 GL_BlendFunc(GL_ONE, GL_ZERO);
2977 for (x = -range;x <= range;x++)
2979 if (!dir){xoffset = 0;yoffset = x;}
2980 else {xoffset = x;yoffset = 0;}
2981 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2982 yoffset /= (float)r_bloomstate.bloomtextureheight;
2983 // compute a texcoord array with the specified x and y offset
2984 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2985 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2986 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2987 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2988 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2989 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2990 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2991 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2992 // this r value looks like a 'dot' particle, fading sharply to
2993 // black at the edges
2994 // (probably not realistic but looks good enough)
2995 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2996 //r = (dir ? 1.0f : brighten)/(range*2+1);
2997 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2998 GL_Color(r, r, r, 1);
2999 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3000 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3001 GL_BlendFunc(GL_ONE, GL_ONE);
3004 // copy the vertically blurred bloom view to a texture
3005 GL_ActiveTexture(0);
3007 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
3008 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3011 // apply subtract last
3012 // (just like it would be in a GLSL shader)
3013 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3015 GL_BlendFunc(GL_ONE, GL_ZERO);
3016 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3017 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3018 GL_Color(1, 1, 1, 1);
3019 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3020 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3022 GL_BlendFunc(GL_ONE, GL_ONE);
3023 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3024 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3025 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3026 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3027 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3028 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3029 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3031 // copy the darkened bloom view to a texture
3032 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3033 GL_ActiveTexture(0);
3035 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
3036 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3040 void R_HDR_RenderBloomTexture(void)
3042 int oldwidth, oldheight;
3044 oldwidth = r_view.width;
3045 oldheight = r_view.height;
3046 r_view.width = r_bloomstate.bloomwidth;
3047 r_view.height = r_bloomstate.bloomheight;
3049 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3050 // TODO: add exposure compensation features
3051 // TODO: add fp16 framebuffer support
3053 r_view.showdebug = false;
3054 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3056 r_view.colorscale /= r_hdr_range.value;
3057 r_waterstate.numwaterplanes = 0;
3058 R_RenderScene(r_waterstate.enabled);
3059 r_view.showdebug = true;
3061 R_ResetViewRendering2D();
3063 R_Bloom_CopyHDRTexture();
3064 R_Bloom_MakeTexture();
3066 R_ResetViewRendering3D();
3069 if (r_timereport_active)
3070 R_TimeReport("clear");
3073 // restore the view settings
3074 r_view.width = oldwidth;
3075 r_view.height = oldheight;
3078 static void R_BlendView(void)
3080 if (r_bloomstate.enabled && r_bloomstate.hdr)
3082 // render high dynamic range bloom effect
3083 // the bloom texture was made earlier this render, so we just need to
3084 // blend it onto the screen...
3085 R_ResetViewRendering2D();
3086 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3087 R_Mesh_ColorPointer(NULL, 0, 0);
3088 GL_Color(1, 1, 1, 1);
3089 GL_BlendFunc(GL_ONE, GL_ONE);
3090 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3091 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3092 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3093 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3095 else if (r_bloomstate.enabled)
3097 // render simple bloom effect
3098 // copy the screen and shrink it and darken it for the bloom process
3099 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3100 // make the bloom texture
3101 R_Bloom_MakeTexture();
3102 // put the original screen image back in place and blend the bloom
3104 R_ResetViewRendering2D();
3105 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3106 R_Mesh_ColorPointer(NULL, 0, 0);
3107 GL_Color(1, 1, 1, 1);
3108 GL_BlendFunc(GL_ONE, GL_ZERO);
3109 // do both in one pass if possible
3110 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3111 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3112 if (r_textureunits.integer >= 2 && gl_combine.integer)
3114 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3115 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3116 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3120 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3121 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3122 // now blend on the bloom texture
3123 GL_BlendFunc(GL_ONE, GL_ONE);
3124 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3125 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3127 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3128 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3130 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3132 // apply a color tint to the whole view
3133 R_ResetViewRendering2D();
3134 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3135 R_Mesh_ColorPointer(NULL, 0, 0);
3136 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3137 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3138 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3142 void R_RenderScene(qboolean addwaterplanes);
3144 matrix4x4_t r_waterscrollmatrix;
3146 void R_UpdateVariables(void)
3150 r_refdef.farclip = 4096;
3151 if (r_refdef.worldmodel)
3152 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3153 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3155 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3156 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3157 r_refdef.polygonfactor = 0;
3158 r_refdef.polygonoffset = 0;
3159 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3160 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3162 r_refdef.rtworld = r_shadow_realtime_world.integer;
3163 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3164 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3165 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3166 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3167 if (r_showsurfaces.integer)
3169 r_refdef.rtworld = false;
3170 r_refdef.rtworldshadows = false;
3171 r_refdef.rtdlight = false;
3172 r_refdef.rtdlightshadows = false;
3173 r_refdef.lightmapintensity = 0;
3176 if (gamemode == GAME_NEHAHRA)
3178 if (gl_fogenable.integer)
3180 r_refdef.oldgl_fogenable = true;
3181 r_refdef.fog_density = gl_fogdensity.value;
3182 r_refdef.fog_red = gl_fogred.value;
3183 r_refdef.fog_green = gl_foggreen.value;
3184 r_refdef.fog_blue = gl_fogblue.value;
3186 else if (r_refdef.oldgl_fogenable)
3188 r_refdef.oldgl_fogenable = false;
3189 r_refdef.fog_density = 0;
3190 r_refdef.fog_red = 0;
3191 r_refdef.fog_green = 0;
3192 r_refdef.fog_blue = 0;
3195 if (r_refdef.fog_density)
3197 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3198 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3199 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3201 if (r_refdef.fog_density)
3203 r_refdef.fogenabled = true;
3204 // this is the point where the fog reaches 0.9986 alpha, which we
3205 // consider a good enough cutoff point for the texture
3206 // (0.9986 * 256 == 255.6)
3207 r_refdef.fogrange = 400 / r_refdef.fog_density;
3208 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3209 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3210 // fog color was already set
3213 r_refdef.fogenabled = false;
3221 void R_RenderView(void)
3223 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3224 return; //Host_Error ("R_RenderView: NULL worldmodel");
3226 R_Shadow_UpdateWorldLightSelection();
3228 R_Bloom_StartFrame();
3229 R_Water_StartFrame();
3232 if (r_timereport_active)
3233 R_TimeReport("setup");
3235 R_ResetViewRendering3D();
3238 if (r_timereport_active)
3239 R_TimeReport("clear");
3241 r_view.showdebug = true;
3243 // this produces a bloom texture to be used in R_BlendView() later
3245 R_HDR_RenderBloomTexture();
3247 r_view.colorscale = r_hdr_scenebrightness.value;
3248 r_waterstate.numwaterplanes = 0;
3249 R_RenderScene(r_waterstate.enabled);
3252 if (r_timereport_active)
3253 R_TimeReport("blendview");
3255 GL_Scissor(0, 0, vid.width, vid.height);
3256 GL_ScissorTest(false);
3260 extern void R_DrawLightningBeams (void);
3261 extern void VM_CL_AddPolygonsToMeshQueue (void);
3262 extern void R_DrawPortals (void);
3263 extern cvar_t cl_locs_show;
3264 static void R_DrawLocs(void);
3265 static void R_DrawEntityBBoxes(void);
3266 void R_RenderScene(qboolean addwaterplanes)
3270 R_ResetViewRendering3D();
3273 if (r_timereport_active)
3274 R_TimeReport("watervis");
3276 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3278 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3279 if (r_timereport_active)
3280 R_TimeReport("waterworld");
3283 // don't let sound skip if going slow
3284 if (r_refdef.extraupdate)
3287 R_DrawModelsAddWaterPlanes();
3288 if (r_timereport_active)
3289 R_TimeReport("watermodels");
3291 R_Water_ProcessPlanes();
3292 if (r_timereport_active)
3293 R_TimeReport("waterscenes");
3296 R_ResetViewRendering3D();
3298 // don't let sound skip if going slow
3299 if (r_refdef.extraupdate)
3302 R_MeshQueue_BeginScene();
3307 if (r_timereport_active)
3308 R_TimeReport("visibility");
3310 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);
3312 if (cl.csqc_vidvars.drawworld)
3314 // don't let sound skip if going slow
3315 if (r_refdef.extraupdate)
3318 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3320 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3321 if (r_timereport_active)
3322 R_TimeReport("worldsky");
3325 if (R_DrawBrushModelsSky() && r_timereport_active)
3326 R_TimeReport("bmodelsky");
3329 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3331 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3332 if (r_timereport_active)
3333 R_TimeReport("worlddepth");
3335 if (r_depthfirst.integer >= 2)
3337 R_DrawModelsDepth();
3338 if (r_timereport_active)
3339 R_TimeReport("modeldepth");
3342 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3344 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3345 if (r_timereport_active)
3346 R_TimeReport("world");
3349 // don't let sound skip if going slow
3350 if (r_refdef.extraupdate)
3354 if (r_timereport_active)
3355 R_TimeReport("models");
3357 // don't let sound skip if going slow
3358 if (r_refdef.extraupdate)
3361 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3363 R_DrawModelShadows();
3365 R_ResetViewRendering3D();
3367 // don't let sound skip if going slow
3368 if (r_refdef.extraupdate)
3372 R_ShadowVolumeLighting(false);
3373 if (r_timereport_active)
3374 R_TimeReport("rtlights");
3376 // don't let sound skip if going slow
3377 if (r_refdef.extraupdate)
3380 if (cl.csqc_vidvars.drawworld)
3382 R_DrawLightningBeams();
3383 if (r_timereport_active)
3384 R_TimeReport("lightning");
3387 if (r_timereport_active)
3388 R_TimeReport("particles");
3391 if (r_timereport_active)
3392 R_TimeReport("explosions");
3395 if (gl_support_fragment_shader)
3397 qglUseProgramObjectARB(0);CHECKGLERROR
3399 VM_CL_AddPolygonsToMeshQueue();
3401 if (r_view.showdebug)
3403 if (cl_locs_show.integer)
3406 if (r_timereport_active)
3407 R_TimeReport("showlocs");
3410 if (r_drawportals.integer)
3413 if (r_timereport_active)
3414 R_TimeReport("portals");
3417 if (r_showbboxes.value > 0)
3419 R_DrawEntityBBoxes();
3420 if (r_timereport_active)
3421 R_TimeReport("bboxes");
3425 if (gl_support_fragment_shader)
3427 qglUseProgramObjectARB(0);CHECKGLERROR
3429 R_MeshQueue_RenderTransparent();
3430 if (r_timereport_active)
3431 R_TimeReport("drawtrans");
3433 if (gl_support_fragment_shader)
3435 qglUseProgramObjectARB(0);CHECKGLERROR
3438 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3440 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3441 if (r_timereport_active)
3442 R_TimeReport("worlddebug");
3443 R_DrawModelsDebug();
3444 if (r_timereport_active)
3445 R_TimeReport("modeldebug");
3448 if (gl_support_fragment_shader)
3450 qglUseProgramObjectARB(0);CHECKGLERROR
3453 if (cl.csqc_vidvars.drawworld)
3456 if (r_timereport_active)
3457 R_TimeReport("coronas");
3460 // don't let sound skip if going slow
3461 if (r_refdef.extraupdate)
3464 R_ResetViewRendering2D();
3467 static const int bboxelements[36] =
3477 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3480 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3481 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3482 GL_DepthMask(false);
3483 GL_DepthRange(0, 1);
3484 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3485 R_Mesh_Matrix(&identitymatrix);
3486 R_Mesh_ResetTextureState();
3488 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3489 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3490 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3491 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3492 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3493 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3494 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3495 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3496 R_FillColors(color4f, 8, cr, cg, cb, ca);
3497 if (r_refdef.fogenabled)
3499 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3501 f1 = FogPoint_World(v);
3503 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3504 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3505 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3508 R_Mesh_VertexPointer(vertex3f, 0, 0);
3509 R_Mesh_ColorPointer(color4f, 0, 0);
3510 R_Mesh_ResetTextureState();
3511 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3514 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3518 prvm_edict_t *edict;
3519 // this function draws bounding boxes of server entities
3523 for (i = 0;i < numsurfaces;i++)
3525 edict = PRVM_EDICT_NUM(surfacelist[i]);
3526 switch ((int)edict->fields.server->solid)
3528 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3529 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3530 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3531 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3532 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3533 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3535 color[3] *= r_showbboxes.value;
3536 color[3] = bound(0, color[3], 1);
3537 GL_DepthTest(!r_showdisabledepthtest.integer);
3538 GL_CullFace(r_view.cullface_front);
3539 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3544 static void R_DrawEntityBBoxes(void)
3547 prvm_edict_t *edict;
3549 // this function draws bounding boxes of server entities
3553 for (i = 0;i < prog->num_edicts;i++)
3555 edict = PRVM_EDICT_NUM(i);
3556 if (edict->priv.server->free)
3558 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3559 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3564 int nomodelelements[24] =
3576 float nomodelvertex3f[6*3] =
3586 float nomodelcolor4f[6*4] =
3588 0.0f, 0.0f, 0.5f, 1.0f,
3589 0.0f, 0.0f, 0.5f, 1.0f,
3590 0.0f, 0.5f, 0.0f, 1.0f,
3591 0.0f, 0.5f, 0.0f, 1.0f,
3592 0.5f, 0.0f, 0.0f, 1.0f,
3593 0.5f, 0.0f, 0.0f, 1.0f
3596 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3601 // this is only called once per entity so numsurfaces is always 1, and
3602 // surfacelist is always {0}, so this code does not handle batches
3603 R_Mesh_Matrix(&ent->matrix);
3605 if (ent->flags & EF_ADDITIVE)
3607 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3608 GL_DepthMask(false);
3610 else if (ent->alpha < 1)
3612 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3613 GL_DepthMask(false);
3617 GL_BlendFunc(GL_ONE, GL_ZERO);
3620 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3621 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3622 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3623 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3624 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3625 if (r_refdef.fogenabled)
3628 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3629 R_Mesh_ColorPointer(color4f, 0, 0);
3630 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3631 f1 = FogPoint_World(org);
3633 for (i = 0, c = color4f;i < 6;i++, c += 4)
3635 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3636 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3637 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3641 else if (ent->alpha != 1)
3643 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3644 R_Mesh_ColorPointer(color4f, 0, 0);
3645 for (i = 0, c = color4f;i < 6;i++, c += 4)
3649 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3650 R_Mesh_ResetTextureState();
3651 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3654 void R_DrawNoModel(entity_render_t *ent)
3657 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3658 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3659 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3661 // R_DrawNoModelCallback(ent, 0);
3664 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3666 vec3_t right1, right2, diff, normal;
3668 VectorSubtract (org2, org1, normal);
3670 // calculate 'right' vector for start
3671 VectorSubtract (r_view.origin, org1, diff);
3672 CrossProduct (normal, diff, right1);
3673 VectorNormalize (right1);
3675 // calculate 'right' vector for end
3676 VectorSubtract (r_view.origin, org2, diff);
3677 CrossProduct (normal, diff, right2);
3678 VectorNormalize (right2);
3680 vert[ 0] = org1[0] + width * right1[0];
3681 vert[ 1] = org1[1] + width * right1[1];
3682 vert[ 2] = org1[2] + width * right1[2];
3683 vert[ 3] = org1[0] - width * right1[0];
3684 vert[ 4] = org1[1] - width * right1[1];
3685 vert[ 5] = org1[2] - width * right1[2];
3686 vert[ 6] = org2[0] - width * right2[0];
3687 vert[ 7] = org2[1] - width * right2[1];
3688 vert[ 8] = org2[2] - width * right2[2];
3689 vert[ 9] = org2[0] + width * right2[0];
3690 vert[10] = org2[1] + width * right2[1];
3691 vert[11] = org2[2] + width * right2[2];
3694 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3696 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)
3701 if (r_refdef.fogenabled)
3702 fog = FogPoint_World(origin);
3704 R_Mesh_Matrix(&identitymatrix);
3705 GL_BlendFunc(blendfunc1, blendfunc2);
3711 GL_CullFace(r_view.cullface_front);
3714 GL_CullFace(r_view.cullface_back);
3716 GL_DepthMask(false);
3717 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3718 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3719 GL_DepthTest(!depthdisable);
3721 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3722 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3723 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3724 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3725 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3726 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3727 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3728 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3729 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3730 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3731 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3732 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3734 R_Mesh_VertexPointer(vertex3f, 0, 0);
3735 R_Mesh_ColorPointer(NULL, 0, 0);
3736 R_Mesh_ResetTextureState();
3737 R_Mesh_TexBind(0, R_GetTexture(texture));
3738 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3739 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3740 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3741 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3743 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3745 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3746 GL_BlendFunc(blendfunc1, GL_ONE);
3748 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);
3749 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3753 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3758 VectorSet(v, x, y, z);
3759 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3760 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3762 if (i == mesh->numvertices)
3764 if (mesh->numvertices < mesh->maxvertices)
3766 VectorCopy(v, vertex3f);
3767 mesh->numvertices++;
3769 return mesh->numvertices;
3775 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3779 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3780 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3781 e = mesh->element3i + mesh->numtriangles * 3;
3782 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3784 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3785 if (mesh->numtriangles < mesh->maxtriangles)
3790 mesh->numtriangles++;
3792 element[1] = element[2];
3796 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3800 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3801 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3802 e = mesh->element3i + mesh->numtriangles * 3;
3803 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3805 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3806 if (mesh->numtriangles < mesh->maxtriangles)
3811 mesh->numtriangles++;
3813 element[1] = element[2];
3817 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3818 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3820 int planenum, planenum2;
3823 mplane_t *plane, *plane2;
3825 double temppoints[2][256*3];
3826 // figure out how large a bounding box we need to properly compute this brush
3828 for (w = 0;w < numplanes;w++)
3829 maxdist = max(maxdist, planes[w].dist);
3830 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3831 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3832 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3836 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3837 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3839 if (planenum2 == planenum)
3841 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);
3844 if (tempnumpoints < 3)
3846 // generate elements forming a triangle fan for this polygon
3847 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3851 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)
3853 texturelayer_t *layer;
3854 layer = t->currentlayers + t->currentnumlayers++;
3856 layer->depthmask = depthmask;
3857 layer->blendfunc1 = blendfunc1;
3858 layer->blendfunc2 = blendfunc2;
3859 layer->texture = texture;
3860 layer->texmatrix = *matrix;
3861 layer->color[0] = r * r_view.colorscale;
3862 layer->color[1] = g * r_view.colorscale;
3863 layer->color[2] = b * r_view.colorscale;
3864 layer->color[3] = a;
3867 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3870 index = parms[2] + r_refdef.time * parms[3];
3871 index -= floor(index);
3875 case Q3WAVEFUNC_NONE:
3876 case Q3WAVEFUNC_NOISE:
3877 case Q3WAVEFUNC_COUNT:
3880 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3881 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3882 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3883 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3884 case Q3WAVEFUNC_TRIANGLE:
3886 f = index - floor(index);
3897 return (float)(parms[0] + parms[1] * f);
3900 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3903 model_t *model = ent->model;
3906 q3shaderinfo_layer_tcmod_t *tcmod;
3908 // switch to an alternate material if this is a q1bsp animated material
3910 texture_t *texture = t;
3911 int s = ent->skinnum;
3912 if ((unsigned int)s >= (unsigned int)model->numskins)
3914 if (model->skinscenes)
3916 if (model->skinscenes[s].framecount > 1)
3917 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3919 s = model->skinscenes[s].firstframe;
3922 t = t + s * model->num_surfaces;
3925 // use an alternate animation if the entity's frame is not 0,
3926 // and only if the texture has an alternate animation
3927 if (ent->frame2 != 0 && t->anim_total[1])
3928 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3930 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3932 texture->currentframe = t;
3935 // update currentskinframe to be a qw skin or animation frame
3936 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3938 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3940 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3941 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3942 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);
3944 t->currentskinframe = r_qwskincache_skinframe[i];
3945 if (t->currentskinframe == NULL)
3946 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3948 else if (t->numskinframes >= 2)
3949 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3950 if (t->backgroundnumskinframes >= 2)
3951 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3953 t->currentmaterialflags = t->basematerialflags;
3954 t->currentalpha = ent->alpha;
3955 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3957 t->currentalpha *= r_wateralpha.value;
3959 * FIXME what is this supposed to do?
3960 // if rendering refraction/reflection, disable transparency
3961 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3962 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3965 if(!r_waterstate.enabled)
3966 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
3967 if (!(ent->flags & RENDER_LIGHT))
3968 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3969 if (ent->effects & EF_ADDITIVE)
3970 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3971 else if (t->currentalpha < 1)
3972 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3973 if (ent->effects & EF_DOUBLESIDED)
3974 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3975 if (ent->effects & EF_NODEPTHTEST)
3976 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3977 if (ent->flags & RENDER_VIEWMODEL)
3978 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3979 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3980 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3982 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3985 switch(tcmod->tcmod)
3989 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3990 matrix = r_waterscrollmatrix;
3992 matrix = identitymatrix;
3994 case Q3TCMOD_ENTITYTRANSLATE:
3995 // this is used in Q3 to allow the gamecode to control texcoord
3996 // scrolling on the entity, which is not supported in darkplaces yet.
3997 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3999 case Q3TCMOD_ROTATE:
4000 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4001 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4002 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4005 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4007 case Q3TCMOD_SCROLL:
4008 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4010 case Q3TCMOD_STRETCH:
4011 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4012 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4014 case Q3TCMOD_TRANSFORM:
4015 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4016 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4017 VectorSet(tcmat + 6, 0 , 0 , 1);
4018 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4019 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4021 case Q3TCMOD_TURBULENT:
4022 // this is handled in the RSurf_PrepareVertices function
4023 matrix = identitymatrix;
4026 // either replace or concatenate the transformation
4028 t->currenttexmatrix = matrix;
4031 matrix4x4_t temp = t->currenttexmatrix;
4032 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4036 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4037 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4038 t->glosstexture = r_texture_black;
4039 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4040 t->backgroundglosstexture = r_texture_black;
4041 t->specularpower = r_shadow_glossexponent.value;
4042 // TODO: store reference values for these in the texture?
4043 t->specularscale = 0;
4044 if (r_shadow_gloss.integer > 0)
4046 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4048 if (r_shadow_glossintensity.value > 0)
4050 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4051 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4052 t->specularscale = r_shadow_glossintensity.value;
4055 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4057 t->glosstexture = r_texture_white;
4058 t->backgroundglosstexture = r_texture_white;
4059 t->specularscale = r_shadow_gloss2intensity.value;
4063 // lightmaps mode looks bad with dlights using actual texturing, so turn
4064 // off the colormap and glossmap, but leave the normalmap on as it still
4065 // accurately represents the shading involved
4066 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4068 t->basetexture = r_texture_white;
4069 t->specularscale = 0;
4072 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4073 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4074 // submodels are biased to avoid z-fighting with world surfaces that they
4075 // may be exactly overlapping (avoids z-fighting artifacts on certain
4076 // doors and things in Quake maps)
4077 if (ent->model->brush.submodel)
4079 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4080 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4083 VectorClear(t->dlightcolor);
4084 t->currentnumlayers = 0;
4085 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4087 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4089 int blendfunc1, blendfunc2, depthmask;
4090 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4092 blendfunc1 = GL_SRC_ALPHA;
4093 blendfunc2 = GL_ONE;
4095 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4097 blendfunc1 = GL_SRC_ALPHA;
4098 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4100 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4102 blendfunc1 = t->customblendfunc[0];
4103 blendfunc2 = t->customblendfunc[1];
4107 blendfunc1 = GL_ONE;
4108 blendfunc2 = GL_ZERO;
4110 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4111 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4113 rtexture_t *currentbasetexture;
4115 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4116 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4117 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4118 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4120 // fullbright is not affected by r_refdef.lightmapintensity
4121 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4122 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4123 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);
4124 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4125 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);
4130 // set the color tint used for lights affecting this surface
4131 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4133 // q3bsp has no lightmap updates, so the lightstylevalue that
4134 // would normally be baked into the lightmap must be
4135 // applied to the color
4136 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4137 if (ent->model->type == mod_brushq3)
4138 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4139 colorscale *= r_refdef.lightmapintensity;
4140 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);
4141 if (r_ambient.value >= (1.0f/64.0f))
4142 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);
4143 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4145 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);
4146 if (r_ambient.value >= (1.0f/64.0f))
4147 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);
4149 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4151 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);
4152 if (r_ambient.value >= (1.0f/64.0f))
4153 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);
4156 if (t->currentskinframe->glow != NULL)
4157 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);
4158 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4160 // if this is opaque use alpha blend which will darken the earlier
4163 // if this is an alpha blended material, all the earlier passes
4164 // were darkened by fog already, so we only need to add the fog
4165 // color ontop through the fog mask texture
4167 // if this is an additive blended material, all the earlier passes
4168 // were darkened by fog already, and we should not add fog color
4169 // (because the background was not darkened, there is no fog color
4170 // that was lost behind it).
4171 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);
4178 void R_UpdateAllTextureInfo(entity_render_t *ent)
4182 for (i = 0;i < ent->model->num_texturesperskin;i++)
4183 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4186 rsurfacestate_t rsurface;
4188 void R_Mesh_ResizeArrays(int newvertices)
4191 if (rsurface.array_size >= newvertices)
4193 if (rsurface.array_modelvertex3f)
4194 Mem_Free(rsurface.array_modelvertex3f);
4195 rsurface.array_size = (newvertices + 1023) & ~1023;
4196 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4197 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4198 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4199 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4200 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4201 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4202 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4203 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4204 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4205 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4206 rsurface.array_color4f = base + rsurface.array_size * 27;
4207 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4210 void RSurf_CleanUp(void)
4213 if (rsurface.mode == RSURFMODE_GLSL)
4215 qglUseProgramObjectARB(0);CHECKGLERROR
4217 GL_AlphaTest(false);
4218 rsurface.mode = RSURFMODE_NONE;
4219 rsurface.uselightmaptexture = false;
4220 rsurface.texture = NULL;
4223 void RSurf_ActiveWorldEntity(void)
4225 model_t *model = r_refdef.worldmodel;
4227 if (rsurface.array_size < model->surfmesh.num_vertices)
4228 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4229 rsurface.matrix = identitymatrix;
4230 rsurface.inversematrix = identitymatrix;
4231 R_Mesh_Matrix(&identitymatrix);
4232 VectorCopy(r_view.origin, rsurface.modelorg);
4233 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4234 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4235 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4236 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4237 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4238 rsurface.frameblend[0].frame = 0;
4239 rsurface.frameblend[0].lerp = 1;
4240 rsurface.frameblend[1].frame = 0;
4241 rsurface.frameblend[1].lerp = 0;
4242 rsurface.frameblend[2].frame = 0;
4243 rsurface.frameblend[2].lerp = 0;
4244 rsurface.frameblend[3].frame = 0;
4245 rsurface.frameblend[3].lerp = 0;
4246 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4247 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4248 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4249 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4250 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4251 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4252 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4253 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4254 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4255 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4256 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4257 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4258 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4259 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4260 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4261 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4262 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4263 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4264 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4265 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4266 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4267 rsurface.modelelement3i = model->surfmesh.data_element3i;
4268 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4269 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4270 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4271 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4272 rsurface.modelsurfaces = model->data_surfaces;
4273 rsurface.generatedvertex = false;
4274 rsurface.vertex3f = rsurface.modelvertex3f;
4275 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4276 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4277 rsurface.svector3f = rsurface.modelsvector3f;
4278 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4279 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4280 rsurface.tvector3f = rsurface.modeltvector3f;
4281 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4282 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4283 rsurface.normal3f = rsurface.modelnormal3f;
4284 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4285 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4286 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4289 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4291 model_t *model = ent->model;
4293 if (rsurface.array_size < model->surfmesh.num_vertices)
4294 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4295 rsurface.matrix = ent->matrix;
4296 rsurface.inversematrix = ent->inversematrix;
4297 R_Mesh_Matrix(&rsurface.matrix);
4298 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4299 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4300 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4301 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4302 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4303 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4304 rsurface.frameblend[0] = ent->frameblend[0];
4305 rsurface.frameblend[1] = ent->frameblend[1];
4306 rsurface.frameblend[2] = ent->frameblend[2];
4307 rsurface.frameblend[3] = ent->frameblend[3];
4308 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4312 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4313 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4314 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4315 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4316 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4318 else if (wantnormals)
4320 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4321 rsurface.modelsvector3f = NULL;
4322 rsurface.modeltvector3f = NULL;
4323 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4324 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4328 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4329 rsurface.modelsvector3f = NULL;
4330 rsurface.modeltvector3f = NULL;
4331 rsurface.modelnormal3f = NULL;
4332 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4334 rsurface.modelvertex3f_bufferobject = 0;
4335 rsurface.modelvertex3f_bufferoffset = 0;
4336 rsurface.modelsvector3f_bufferobject = 0;
4337 rsurface.modelsvector3f_bufferoffset = 0;
4338 rsurface.modeltvector3f_bufferobject = 0;
4339 rsurface.modeltvector3f_bufferoffset = 0;
4340 rsurface.modelnormal3f_bufferobject = 0;
4341 rsurface.modelnormal3f_bufferoffset = 0;
4342 rsurface.generatedvertex = true;
4346 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4347 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4348 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4349 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4350 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4351 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4352 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4353 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4354 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4355 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4356 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4357 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4358 rsurface.generatedvertex = false;
4360 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4361 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4362 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4363 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4364 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4365 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4366 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4367 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4368 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4369 rsurface.modelelement3i = model->surfmesh.data_element3i;
4370 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4371 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4372 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4373 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4374 rsurface.modelsurfaces = model->data_surfaces;
4375 rsurface.vertex3f = rsurface.modelvertex3f;
4376 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4377 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4378 rsurface.svector3f = rsurface.modelsvector3f;
4379 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4380 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4381 rsurface.tvector3f = rsurface.modeltvector3f;
4382 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4383 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4384 rsurface.normal3f = rsurface.modelnormal3f;
4385 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4386 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4387 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4390 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4391 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4394 int texturesurfaceindex;
4399 const float *v1, *in_tc;
4401 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4403 q3shaderinfo_deform_t *deform;
4404 // 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
4405 if (rsurface.generatedvertex)
4407 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4408 generatenormals = true;
4409 for (i = 0;i < Q3MAXDEFORMS;i++)
4411 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4413 generatetangents = true;
4414 generatenormals = true;
4416 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4417 generatenormals = true;
4419 if (generatenormals && !rsurface.modelnormal3f)
4421 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4422 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4423 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4424 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4426 if (generatetangents && !rsurface.modelsvector3f)
4428 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4429 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4430 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4431 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4432 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4433 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4434 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);
4437 rsurface.vertex3f = rsurface.modelvertex3f;
4438 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4439 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4440 rsurface.svector3f = rsurface.modelsvector3f;
4441 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4442 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4443 rsurface.tvector3f = rsurface.modeltvector3f;
4444 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4445 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4446 rsurface.normal3f = rsurface.modelnormal3f;
4447 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4448 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4449 // if vertices are deformed (sprite flares and things in maps, possibly
4450 // water waves, bulges and other deformations), generate them into
4451 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4452 // (may be static model data or generated data for an animated model, or
4453 // the previous deform pass)
4454 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4456 switch (deform->deform)
4459 case Q3DEFORM_PROJECTIONSHADOW:
4460 case Q3DEFORM_TEXT0:
4461 case Q3DEFORM_TEXT1:
4462 case Q3DEFORM_TEXT2:
4463 case Q3DEFORM_TEXT3:
4464 case Q3DEFORM_TEXT4:
4465 case Q3DEFORM_TEXT5:
4466 case Q3DEFORM_TEXT6:
4467 case Q3DEFORM_TEXT7:
4470 case Q3DEFORM_AUTOSPRITE:
4471 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4472 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4473 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4474 VectorNormalize(newforward);
4475 VectorNormalize(newright);
4476 VectorNormalize(newup);
4477 // make deformed versions of only the model vertices used by the specified surfaces
4478 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4480 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4481 // a single autosprite surface can contain multiple sprites...
4482 for (j = 0;j < surface->num_vertices - 3;j += 4)
4484 VectorClear(center);
4485 for (i = 0;i < 4;i++)
4486 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4487 VectorScale(center, 0.25f, center);
4488 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4489 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4490 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4491 for (i = 0;i < 4;i++)
4493 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4494 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4497 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);
4498 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);
4500 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4501 rsurface.vertex3f_bufferobject = 0;
4502 rsurface.vertex3f_bufferoffset = 0;
4503 rsurface.svector3f = rsurface.array_deformedsvector3f;
4504 rsurface.svector3f_bufferobject = 0;
4505 rsurface.svector3f_bufferoffset = 0;
4506 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4507 rsurface.tvector3f_bufferobject = 0;
4508 rsurface.tvector3f_bufferoffset = 0;
4509 rsurface.normal3f = rsurface.array_deformednormal3f;
4510 rsurface.normal3f_bufferobject = 0;
4511 rsurface.normal3f_bufferoffset = 0;
4513 case Q3DEFORM_AUTOSPRITE2:
4514 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4515 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4516 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4517 VectorNormalize(newforward);
4518 VectorNormalize(newright);
4519 VectorNormalize(newup);
4520 // make deformed versions of only the model vertices used by the specified surfaces
4521 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4523 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4524 const float *v1, *v2;
4534 memset(shortest, 0, sizeof(shortest));
4535 // a single autosprite surface can contain multiple sprites...
4536 for (j = 0;j < surface->num_vertices - 3;j += 4)
4538 VectorClear(center);
4539 for (i = 0;i < 4;i++)
4540 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4541 VectorScale(center, 0.25f, center);
4542 // find the two shortest edges, then use them to define the
4543 // axis vectors for rotating around the central axis
4544 for (i = 0;i < 6;i++)
4546 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4547 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4549 Debug_PolygonBegin(NULL, 0, false, 0);
4550 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4551 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);
4552 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4555 l = VectorDistance2(v1, v2);
4556 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4558 l += (1.0f / 1024.0f);
4559 if (shortest[0].length2 > l || i == 0)
4561 shortest[1] = shortest[0];
4562 shortest[0].length2 = l;
4563 shortest[0].v1 = v1;
4564 shortest[0].v2 = v2;
4566 else if (shortest[1].length2 > l || i == 1)
4568 shortest[1].length2 = l;
4569 shortest[1].v1 = v1;
4570 shortest[1].v2 = v2;
4573 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4574 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4576 Debug_PolygonBegin(NULL, 0, false, 0);
4577 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4578 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);
4579 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4582 // this calculates the right vector from the shortest edge
4583 // and the up vector from the edge midpoints
4584 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4585 VectorNormalize(right);
4586 VectorSubtract(end, start, up);
4587 VectorNormalize(up);
4588 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4589 //VectorSubtract(rsurface.modelorg, center, forward);
4590 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4591 VectorNegate(forward, forward);
4592 VectorReflect(forward, 0, up, forward);
4593 VectorNormalize(forward);
4594 CrossProduct(up, forward, newright);
4595 VectorNormalize(newright);
4597 Debug_PolygonBegin(NULL, 0, false, 0);
4598 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);
4599 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4600 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4604 Debug_PolygonBegin(NULL, 0, false, 0);
4605 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4606 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4607 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4610 // rotate the quad around the up axis vector, this is made
4611 // especially easy by the fact we know the quad is flat,
4612 // so we only have to subtract the center position and
4613 // measure distance along the right vector, and then
4614 // multiply that by the newright vector and add back the
4616 // we also need to subtract the old position to undo the
4617 // displacement from the center, which we do with a
4618 // DotProduct, the subtraction/addition of center is also
4619 // optimized into DotProducts here
4620 l = DotProduct(right, center);
4621 for (i = 0;i < 4;i++)
4623 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4624 f = DotProduct(right, v1) - l;
4625 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4628 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);
4629 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);
4631 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4632 rsurface.vertex3f_bufferobject = 0;
4633 rsurface.vertex3f_bufferoffset = 0;
4634 rsurface.svector3f = rsurface.array_deformedsvector3f;
4635 rsurface.svector3f_bufferobject = 0;
4636 rsurface.svector3f_bufferoffset = 0;
4637 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4638 rsurface.tvector3f_bufferobject = 0;
4639 rsurface.tvector3f_bufferoffset = 0;
4640 rsurface.normal3f = rsurface.array_deformednormal3f;
4641 rsurface.normal3f_bufferobject = 0;
4642 rsurface.normal3f_bufferoffset = 0;
4644 case Q3DEFORM_NORMAL:
4645 // deform the normals to make reflections wavey
4646 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4648 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4649 for (j = 0;j < surface->num_vertices;j++)
4652 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4653 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4654 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4655 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4656 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4657 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4658 VectorNormalize(normal);
4660 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);
4662 rsurface.svector3f = rsurface.array_deformedsvector3f;
4663 rsurface.svector3f_bufferobject = 0;
4664 rsurface.svector3f_bufferoffset = 0;
4665 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4666 rsurface.tvector3f_bufferobject = 0;
4667 rsurface.tvector3f_bufferoffset = 0;
4668 rsurface.normal3f = rsurface.array_deformednormal3f;
4669 rsurface.normal3f_bufferobject = 0;
4670 rsurface.normal3f_bufferoffset = 0;
4673 // deform vertex array to make wavey water and flags and such
4674 waveparms[0] = deform->waveparms[0];
4675 waveparms[1] = deform->waveparms[1];
4676 waveparms[2] = deform->waveparms[2];
4677 waveparms[3] = deform->waveparms[3];
4678 // this is how a divisor of vertex influence on deformation
4679 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4680 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4684 for (j = 0;j < surface->num_vertices;j++)
4686 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4687 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4688 // if the wavefunc depends on time, evaluate it per-vertex
4691 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4692 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4694 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4697 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4698 rsurface.vertex3f_bufferobject = 0;
4699 rsurface.vertex3f_bufferoffset = 0;
4701 case Q3DEFORM_BULGE:
4702 // deform vertex array to make the surface have moving bulges
4703 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4705 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4706 for (j = 0;j < surface->num_vertices;j++)
4708 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4709 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4712 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4713 rsurface.vertex3f_bufferobject = 0;
4714 rsurface.vertex3f_bufferoffset = 0;
4717 // deform vertex array
4718 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4719 VectorScale(deform->parms, scale, waveparms);
4720 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4722 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4723 for (j = 0;j < surface->num_vertices;j++)
4724 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4726 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4727 rsurface.vertex3f_bufferobject = 0;
4728 rsurface.vertex3f_bufferoffset = 0;
4732 // generate texcoords based on the chosen texcoord source
4733 switch(rsurface.texture->tcgen.tcgen)
4736 case Q3TCGEN_TEXTURE:
4737 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4738 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4739 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4741 case Q3TCGEN_LIGHTMAP:
4742 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4743 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4744 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4746 case Q3TCGEN_VECTOR:
4747 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4749 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4750 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)
4752 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4753 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4756 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4757 rsurface.texcoordtexture2f_bufferobject = 0;
4758 rsurface.texcoordtexture2f_bufferoffset = 0;
4760 case Q3TCGEN_ENVIRONMENT:
4761 // make environment reflections using a spheremap
4762 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4764 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4765 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4766 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4767 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4768 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4770 float l, d, eyedir[3];
4771 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4772 l = 0.5f / VectorLength(eyedir);
4773 d = DotProduct(normal, eyedir)*2;
4774 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4775 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4778 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4779 rsurface.texcoordtexture2f_bufferobject = 0;
4780 rsurface.texcoordtexture2f_bufferoffset = 0;
4783 // the only tcmod that needs software vertex processing is turbulent, so
4784 // check for it here and apply the changes if needed
4785 // and we only support that as the first one
4786 // (handling a mixture of turbulent and other tcmods would be problematic
4787 // without punting it entirely to a software path)
4788 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4790 amplitude = rsurface.texture->tcmods[0].parms[1];
4791 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4795 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)
4797 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4798 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4801 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4802 rsurface.texcoordtexture2f_bufferobject = 0;
4803 rsurface.texcoordtexture2f_bufferoffset = 0;
4805 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4806 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4807 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4808 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4811 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4814 const msurface_t *surface = texturesurfacelist[0];
4815 const msurface_t *surface2;
4820 // TODO: lock all array ranges before render, rather than on each surface
4821 if (texturenumsurfaces == 1)
4823 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4824 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));
4826 else if (r_batchmode.integer == 2)
4828 #define MAXBATCHTRIANGLES 4096
4829 int batchtriangles = 0;
4830 int batchelements[MAXBATCHTRIANGLES*3];
4831 for (i = 0;i < texturenumsurfaces;i = j)
4833 surface = texturesurfacelist[i];
4835 if (surface->num_triangles > MAXBATCHTRIANGLES)
4837 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));
4840 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4841 batchtriangles = surface->num_triangles;
4842 firstvertex = surface->num_firstvertex;
4843 endvertex = surface->num_firstvertex + surface->num_vertices;
4844 for (;j < texturenumsurfaces;j++)
4846 surface2 = texturesurfacelist[j];
4847 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4849 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4850 batchtriangles += surface2->num_triangles;
4851 firstvertex = min(firstvertex, surface2->num_firstvertex);
4852 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4854 surface2 = texturesurfacelist[j-1];
4855 numvertices = endvertex - firstvertex;
4856 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4859 else if (r_batchmode.integer == 1)
4861 for (i = 0;i < texturenumsurfaces;i = j)
4863 surface = texturesurfacelist[i];
4864 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4865 if (texturesurfacelist[j] != surface2)
4867 surface2 = texturesurfacelist[j-1];
4868 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4869 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4870 GL_LockArrays(surface->num_firstvertex, numvertices);
4871 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4876 for (i = 0;i < texturenumsurfaces;i++)
4878 surface = texturesurfacelist[i];
4879 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4880 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));
4885 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4887 int i, planeindex, vertexindex;
4891 r_waterstate_waterplane_t *p, *bestp;
4892 msurface_t *surface;
4893 if (r_waterstate.renderingscene)
4895 for (i = 0;i < texturenumsurfaces;i++)
4897 surface = texturesurfacelist[i];
4898 if (lightmaptexunit >= 0)
4899 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4900 if (deluxemaptexunit >= 0)
4901 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4902 // pick the closest matching water plane
4905 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4908 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4910 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4911 d += fabs(PlaneDiff(vert, &p->plane));
4913 if (bestd > d || !bestp)
4921 if (refractiontexunit >= 0)
4922 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4923 if (reflectiontexunit >= 0)
4924 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4928 if (refractiontexunit >= 0)
4929 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4930 if (reflectiontexunit >= 0)
4931 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4933 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4934 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));
4938 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4942 const msurface_t *surface = texturesurfacelist[0];
4943 const msurface_t *surface2;
4948 // TODO: lock all array ranges before render, rather than on each surface
4949 if (texturenumsurfaces == 1)
4951 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4952 if (deluxemaptexunit >= 0)
4953 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4954 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4955 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4957 else if (r_batchmode.integer == 2)
4959 #define MAXBATCHTRIANGLES 4096
4960 int batchtriangles = 0;
4961 int batchelements[MAXBATCHTRIANGLES*3];
4962 for (i = 0;i < texturenumsurfaces;i = j)
4964 surface = texturesurfacelist[i];
4965 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4966 if (deluxemaptexunit >= 0)
4967 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4969 if (surface->num_triangles > MAXBATCHTRIANGLES)
4971 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));
4974 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4975 batchtriangles = surface->num_triangles;
4976 firstvertex = surface->num_firstvertex;
4977 endvertex = surface->num_firstvertex + surface->num_vertices;
4978 for (;j < texturenumsurfaces;j++)
4980 surface2 = texturesurfacelist[j];
4981 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4983 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4984 batchtriangles += surface2->num_triangles;
4985 firstvertex = min(firstvertex, surface2->num_firstvertex);
4986 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4988 surface2 = texturesurfacelist[j-1];
4989 numvertices = endvertex - firstvertex;
4990 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4993 else if (r_batchmode.integer == 1)
4996 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4997 for (i = 0;i < texturenumsurfaces;i = j)
4999 surface = texturesurfacelist[i];
5000 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5001 if (texturesurfacelist[j] != surface2)
5003 Con_Printf(" %i", j - i);
5006 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5008 for (i = 0;i < texturenumsurfaces;i = j)
5010 surface = texturesurfacelist[i];
5011 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5012 if (deluxemaptexunit >= 0)
5013 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5014 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5015 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5018 Con_Printf(" %i", j - i);
5020 surface2 = texturesurfacelist[j-1];
5021 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5022 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5023 GL_LockArrays(surface->num_firstvertex, numvertices);
5024 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5032 for (i = 0;i < texturenumsurfaces;i++)
5034 surface = texturesurfacelist[i];
5035 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5036 if (deluxemaptexunit >= 0)
5037 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5038 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5039 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));
5044 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5047 int texturesurfaceindex;
5048 if (r_showsurfaces.integer == 2)
5050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5053 for (j = 0;j < surface->num_triangles;j++)
5055 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5056 GL_Color(f, f, f, 1);
5057 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)));
5063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5066 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5067 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);
5068 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5069 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));
5074 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5076 int texturesurfaceindex;
5080 if (rsurface.lightmapcolor4f)
5082 // generate color arrays for the surfaces in this list
5083 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5085 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5086 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)
5088 f = FogPoint_Model(v);
5098 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5100 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5101 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)
5103 f = FogPoint_Model(v);
5111 rsurface.lightmapcolor4f = rsurface.array_color4f;
5112 rsurface.lightmapcolor4f_bufferobject = 0;
5113 rsurface.lightmapcolor4f_bufferoffset = 0;
5116 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5118 int texturesurfaceindex;
5121 if (!rsurface.lightmapcolor4f)
5123 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5125 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5126 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)
5134 rsurface.lightmapcolor4f = rsurface.array_color4f;
5135 rsurface.lightmapcolor4f_bufferobject = 0;
5136 rsurface.lightmapcolor4f_bufferoffset = 0;
5139 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5142 rsurface.lightmapcolor4f = NULL;
5143 rsurface.lightmapcolor4f_bufferobject = 0;
5144 rsurface.lightmapcolor4f_bufferoffset = 0;
5145 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5146 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5147 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5148 GL_Color(r, g, b, a);
5149 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5152 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5154 // TODO: optimize applyfog && applycolor case
5155 // just apply fog if necessary, and tint the fog color array if necessary
5156 rsurface.lightmapcolor4f = NULL;
5157 rsurface.lightmapcolor4f_bufferobject = 0;
5158 rsurface.lightmapcolor4f_bufferoffset = 0;
5159 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5160 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5161 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5162 GL_Color(r, g, b, a);
5163 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5166 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5168 int texturesurfaceindex;
5172 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5174 // generate color arrays for the surfaces in this list
5175 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5177 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5178 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5180 if (surface->lightmapinfo->samples)
5182 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5183 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5184 VectorScale(lm, scale, c);
5185 if (surface->lightmapinfo->styles[1] != 255)
5187 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5189 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5190 VectorMA(c, scale, lm, c);
5191 if (surface->lightmapinfo->styles[2] != 255)
5194 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5195 VectorMA(c, scale, lm, c);
5196 if (surface->lightmapinfo->styles[3] != 255)
5199 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5200 VectorMA(c, scale, lm, c);
5210 rsurface.lightmapcolor4f = rsurface.array_color4f;
5211 rsurface.lightmapcolor4f_bufferobject = 0;
5212 rsurface.lightmapcolor4f_bufferoffset = 0;
5216 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5217 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5218 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5220 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5221 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5222 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5223 GL_Color(r, g, b, a);
5224 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5227 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5229 int texturesurfaceindex;
5233 vec3_t ambientcolor;
5234 vec3_t diffusecolor;
5238 VectorCopy(rsurface.modellight_lightdir, lightdir);
5239 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5240 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5241 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5242 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5243 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5244 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5245 if (VectorLength2(diffusecolor) > 0)
5247 // generate color arrays for the surfaces in this list
5248 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5250 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5251 int numverts = surface->num_vertices;
5252 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5253 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5254 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5255 // q3-style directional shading
5256 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5258 if ((f = DotProduct(c2, lightdir)) > 0)
5259 VectorMA(ambientcolor, f, diffusecolor, c);
5261 VectorCopy(ambientcolor, c);
5270 rsurface.lightmapcolor4f = rsurface.array_color4f;
5271 rsurface.lightmapcolor4f_bufferobject = 0;
5272 rsurface.lightmapcolor4f_bufferoffset = 0;
5276 r = ambientcolor[0];
5277 g = ambientcolor[1];
5278 b = ambientcolor[2];
5279 rsurface.lightmapcolor4f = NULL;
5280 rsurface.lightmapcolor4f_bufferobject = 0;
5281 rsurface.lightmapcolor4f_bufferoffset = 0;
5283 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5284 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5285 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5286 GL_Color(r, g, b, a);
5287 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5290 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5292 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5293 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5294 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5295 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5296 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5298 rsurface.mode = RSURFMODE_SHOWSURFACES;
5300 GL_BlendFunc(GL_ONE, GL_ZERO);
5301 R_Mesh_ColorPointer(NULL, 0, 0);
5302 R_Mesh_ResetTextureState();
5304 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5305 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5308 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5310 // transparent sky would be ridiculous
5311 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5313 if (rsurface.mode != RSURFMODE_SKY)
5315 if (rsurface.mode == RSURFMODE_GLSL)
5317 qglUseProgramObjectARB(0);CHECKGLERROR
5319 rsurface.mode = RSURFMODE_SKY;
5323 skyrendernow = false;
5325 // restore entity matrix
5326 R_Mesh_Matrix(&rsurface.matrix);
5328 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5329 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5330 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5331 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5333 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5334 // skymasking on them, and Quake3 never did sky masking (unlike
5335 // software Quake and software Quake2), so disable the sky masking
5336 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5337 // and skymasking also looks very bad when noclipping outside the
5338 // level, so don't use it then either.
5339 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5341 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5342 R_Mesh_ColorPointer(NULL, 0, 0);
5343 R_Mesh_ResetTextureState();
5344 if (skyrendermasked)
5346 // depth-only (masking)
5347 GL_ColorMask(0,0,0,0);
5348 // just to make sure that braindead drivers don't draw
5349 // anything despite that colormask...
5350 GL_BlendFunc(GL_ZERO, GL_ONE);
5355 GL_BlendFunc(GL_ONE, GL_ZERO);
5357 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5358 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5359 if (skyrendermasked)
5360 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5364 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5366 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5369 if (rsurface.mode != RSURFMODE_GLSL)
5371 rsurface.mode = RSURFMODE_GLSL;
5372 R_Mesh_ResetTextureState();
5375 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5376 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5377 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5378 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5379 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5380 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5381 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5382 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5384 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5385 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5386 R_Mesh_ColorPointer(NULL, 0, 0);
5388 else if (rsurface.uselightmaptexture)
5390 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5391 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5392 R_Mesh_ColorPointer(NULL, 0, 0);
5396 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5397 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5398 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5400 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5401 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5402 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5404 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5406 // render background
5407 GL_BlendFunc(GL_ONE, GL_ZERO);
5409 GL_AlphaTest(false);
5411 GL_Color(1, 1, 1, 1);
5412 R_Mesh_ColorPointer(NULL, 0, 0);
5414 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5415 if (r_glsl_permutation)
5417 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5418 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5419 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5420 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5421 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5422 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5423 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5426 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5427 GL_DepthMask(false);
5428 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5429 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5431 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5432 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5433 R_Mesh_ColorPointer(NULL, 0, 0);
5435 else if (rsurface.uselightmaptexture)
5437 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5438 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5439 R_Mesh_ColorPointer(NULL, 0, 0);
5443 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5444 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5445 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5447 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5448 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5451 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5452 if (!r_glsl_permutation)
5455 if (rsurface.lightmode == 2)
5456 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5458 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5459 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5460 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5461 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5462 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5463 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5464 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]);
5466 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5468 GL_BlendFunc(GL_ONE, GL_ZERO);
5470 GL_AlphaTest(false);
5473 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5475 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5476 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);
5478 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5482 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5483 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);
5485 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5487 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5492 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5494 // OpenGL 1.3 path - anything not completely ancient
5495 int texturesurfaceindex;
5496 qboolean applycolor;
5500 const texturelayer_t *layer;
5501 if (rsurface.mode != RSURFMODE_MULTIPASS)
5502 rsurface.mode = RSURFMODE_MULTIPASS;
5503 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5505 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5508 int layertexrgbscale;
5509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5511 if (layerindex == 0)
5515 GL_AlphaTest(false);
5516 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5519 GL_DepthMask(layer->depthmask);
5520 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5521 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5523 layertexrgbscale = 4;
5524 VectorScale(layer->color, 0.25f, layercolor);
5526 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5528 layertexrgbscale = 2;
5529 VectorScale(layer->color, 0.5f, layercolor);
5533 layertexrgbscale = 1;
5534 VectorScale(layer->color, 1.0f, layercolor);
5536 layercolor[3] = layer->color[3];
5537 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5538 R_Mesh_ColorPointer(NULL, 0, 0);
5539 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5540 switch (layer->type)
5542 case TEXTURELAYERTYPE_LITTEXTURE:
5543 memset(&m, 0, sizeof(m));
5544 m.tex[0] = R_GetTexture(r_texture_white);
5545 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5546 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5547 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5548 m.tex[1] = R_GetTexture(layer->texture);
5549 m.texmatrix[1] = layer->texmatrix;
5550 m.texrgbscale[1] = layertexrgbscale;
5551 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5552 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5553 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5554 R_Mesh_TextureState(&m);
5555 if (rsurface.lightmode == 2)
5556 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5557 else if (rsurface.uselightmaptexture)
5558 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5560 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5562 case TEXTURELAYERTYPE_TEXTURE:
5563 memset(&m, 0, sizeof(m));
5564 m.tex[0] = R_GetTexture(layer->texture);
5565 m.texmatrix[0] = layer->texmatrix;
5566 m.texrgbscale[0] = layertexrgbscale;
5567 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5568 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5569 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5570 R_Mesh_TextureState(&m);
5571 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5573 case TEXTURELAYERTYPE_FOG:
5574 memset(&m, 0, sizeof(m));
5575 m.texrgbscale[0] = layertexrgbscale;
5578 m.tex[0] = R_GetTexture(layer->texture);
5579 m.texmatrix[0] = layer->texmatrix;
5580 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5581 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5582 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5584 R_Mesh_TextureState(&m);
5585 // generate a color array for the fog pass
5586 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5587 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5591 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5592 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)
5594 f = 1 - FogPoint_Model(v);
5595 c[0] = layercolor[0];
5596 c[1] = layercolor[1];
5597 c[2] = layercolor[2];
5598 c[3] = f * layercolor[3];
5601 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5604 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5606 GL_LockArrays(0, 0);
5609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5611 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5612 GL_AlphaTest(false);
5616 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5618 // OpenGL 1.1 - crusty old voodoo path
5619 int texturesurfaceindex;
5623 const texturelayer_t *layer;
5624 if (rsurface.mode != RSURFMODE_MULTIPASS)
5625 rsurface.mode = RSURFMODE_MULTIPASS;
5626 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5628 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5632 if (layerindex == 0)
5636 GL_AlphaTest(false);
5637 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5640 GL_DepthMask(layer->depthmask);
5641 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5642 R_Mesh_ColorPointer(NULL, 0, 0);
5643 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5644 switch (layer->type)
5646 case TEXTURELAYERTYPE_LITTEXTURE:
5647 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5649 // two-pass lit texture with 2x rgbscale
5650 // first the lightmap pass
5651 memset(&m, 0, sizeof(m));
5652 m.tex[0] = R_GetTexture(r_texture_white);
5653 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5654 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5655 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5656 R_Mesh_TextureState(&m);
5657 if (rsurface.lightmode == 2)
5658 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5659 else if (rsurface.uselightmaptexture)
5660 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5662 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5663 GL_LockArrays(0, 0);
5664 // then apply the texture to it
5665 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5666 memset(&m, 0, sizeof(m));
5667 m.tex[0] = R_GetTexture(layer->texture);
5668 m.texmatrix[0] = layer->texmatrix;
5669 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5670 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5671 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5672 R_Mesh_TextureState(&m);
5673 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);
5677 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5678 memset(&m, 0, sizeof(m));
5679 m.tex[0] = R_GetTexture(layer->texture);
5680 m.texmatrix[0] = layer->texmatrix;
5681 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5682 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5683 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5684 R_Mesh_TextureState(&m);
5685 if (rsurface.lightmode == 2)
5686 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);
5688 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);
5691 case TEXTURELAYERTYPE_TEXTURE:
5692 // singletexture unlit texture with transparency support
5693 memset(&m, 0, sizeof(m));
5694 m.tex[0] = R_GetTexture(layer->texture);
5695 m.texmatrix[0] = layer->texmatrix;
5696 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5697 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5698 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5699 R_Mesh_TextureState(&m);
5700 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);
5702 case TEXTURELAYERTYPE_FOG:
5703 // singletexture fogging
5704 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5707 memset(&m, 0, sizeof(m));
5708 m.tex[0] = R_GetTexture(layer->texture);
5709 m.texmatrix[0] = layer->texmatrix;
5710 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5711 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5712 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5713 R_Mesh_TextureState(&m);
5716 R_Mesh_ResetTextureState();
5717 // generate a color array for the fog pass
5718 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5722 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5723 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)
5725 f = 1 - FogPoint_Model(v);
5726 c[0] = layer->color[0];
5727 c[1] = layer->color[1];
5728 c[2] = layer->color[2];
5729 c[3] = f * layer->color[3];
5732 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5735 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5737 GL_LockArrays(0, 0);
5740 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5742 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5743 GL_AlphaTest(false);
5747 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5749 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5751 rsurface.rtlight = NULL;
5755 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5757 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5759 if (rsurface.mode != RSURFMODE_MULTIPASS)
5760 rsurface.mode = RSURFMODE_MULTIPASS;
5761 if (r_depthfirst.integer == 3)
5763 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5764 if (!r_view.showdebug)
5765 GL_Color(0, 0, 0, 1);
5767 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5771 GL_ColorMask(0,0,0,0);
5774 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5775 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5776 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5778 GL_BlendFunc(GL_ONE, GL_ZERO);
5780 GL_AlphaTest(false);
5781 R_Mesh_ColorPointer(NULL, 0, 0);
5782 R_Mesh_ResetTextureState();
5783 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5784 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5785 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5786 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5788 else if (r_depthfirst.integer == 3)
5790 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5792 GL_Color(0, 0, 0, 1);
5793 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5795 else if (r_showsurfaces.integer)
5797 if (rsurface.mode != RSURFMODE_MULTIPASS)
5798 rsurface.mode = RSURFMODE_MULTIPASS;
5799 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5800 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5802 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5803 GL_BlendFunc(GL_ONE, GL_ZERO);
5804 GL_DepthMask(writedepth);
5806 GL_AlphaTest(false);
5807 R_Mesh_ColorPointer(NULL, 0, 0);
5808 R_Mesh_ResetTextureState();
5809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5810 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5811 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5813 else if (gl_lightmaps.integer)
5816 if (rsurface.mode != RSURFMODE_MULTIPASS)
5817 rsurface.mode = RSURFMODE_MULTIPASS;
5818 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5820 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5821 GL_BlendFunc(GL_ONE, GL_ZERO);
5822 GL_DepthMask(writedepth);
5824 GL_AlphaTest(false);
5825 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5826 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5827 R_Mesh_ColorPointer(NULL, 0, 0);
5828 memset(&m, 0, sizeof(m));
5829 m.tex[0] = R_GetTexture(r_texture_white);
5830 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5831 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5832 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5833 R_Mesh_TextureState(&m);
5834 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5835 if (rsurface.lightmode == 2)
5836 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5837 else if (rsurface.uselightmaptexture)
5838 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5840 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5841 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5843 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5845 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5846 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5848 else if (rsurface.texture->currentnumlayers)
5850 // write depth for anything we skipped on the depth-only pass earlier
5851 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5853 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5854 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5855 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5856 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5857 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5858 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5859 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5860 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5861 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5862 if (r_glsl.integer && gl_support_fragment_shader)
5863 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5864 else if (gl_combine.integer && r_textureunits.integer >= 2)
5865 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5867 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5868 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5871 GL_LockArrays(0, 0);
5874 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5877 int texturenumsurfaces, endsurface;
5879 msurface_t *surface;
5880 msurface_t *texturesurfacelist[1024];
5882 // if the model is static it doesn't matter what value we give for
5883 // wantnormals and wanttangents, so this logic uses only rules applicable
5884 // to a model, knowing that they are meaningless otherwise
5885 if (ent == r_refdef.worldentity)
5886 RSurf_ActiveWorldEntity();
5887 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5888 RSurf_ActiveModelEntity(ent, false, false);
5890 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5892 for (i = 0;i < numsurfaces;i = j)
5895 surface = rsurface.modelsurfaces + surfacelist[i];
5896 texture = surface->texture;
5897 R_UpdateTextureInfo(ent, texture);
5898 rsurface.texture = texture->currentframe;
5899 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5900 // scan ahead until we find a different texture
5901 endsurface = min(i + 1024, numsurfaces);
5902 texturenumsurfaces = 0;
5903 texturesurfacelist[texturenumsurfaces++] = surface;
5904 for (;j < endsurface;j++)
5906 surface = rsurface.modelsurfaces + surfacelist[j];
5907 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5909 texturesurfacelist[texturenumsurfaces++] = surface;
5911 // render the range of surfaces
5912 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5918 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5921 vec3_t tempcenter, center;
5923 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5926 for (i = 0;i < numsurfaces;i++)
5927 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5928 R_Water_AddWaterPlane(surfacelist[i]);
5931 // break the surface list down into batches by texture and use of lightmapping
5932 for (i = 0;i < numsurfaces;i = j)
5935 // texture is the base texture pointer, rsurface.texture is the
5936 // current frame/skin the texture is directing us to use (for example
5937 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5938 // use skin 1 instead)
5939 texture = surfacelist[i]->texture;
5940 rsurface.texture = texture->currentframe;
5941 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5942 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5944 // if this texture is not the kind we want, skip ahead to the next one
5945 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5949 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5951 // transparent surfaces get pushed off into the transparent queue
5952 const msurface_t *surface = surfacelist[i];
5955 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5956 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5957 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5958 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5959 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5963 // simply scan ahead until we find a different texture or lightmap state
5964 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5966 // render the range of surfaces
5967 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5972 float locboxvertex3f[6*4*3] =
5974 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5975 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5976 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5977 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5978 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5979 1,0,0, 0,0,0, 0,1,0, 1,1,0
5982 int locboxelement3i[6*2*3] =
5992 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5995 cl_locnode_t *loc = (cl_locnode_t *)ent;
5997 float vertex3f[6*4*3];
5999 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6000 GL_DepthMask(false);
6001 GL_DepthRange(0, 1);
6002 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6004 GL_CullFace(GL_NONE);
6005 R_Mesh_Matrix(&identitymatrix);
6007 R_Mesh_VertexPointer(vertex3f, 0, 0);
6008 R_Mesh_ColorPointer(NULL, 0, 0);
6009 R_Mesh_ResetTextureState();
6012 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6013 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6014 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6015 surfacelist[0] < 0 ? 0.5f : 0.125f);
6017 if (VectorCompare(loc->mins, loc->maxs))
6019 VectorSet(size, 2, 2, 2);
6020 VectorMA(loc->mins, -0.5f, size, mins);
6024 VectorCopy(loc->mins, mins);
6025 VectorSubtract(loc->maxs, loc->mins, size);
6028 for (i = 0;i < 6*4*3;)
6029 for (j = 0;j < 3;j++, i++)
6030 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6032 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6035 void R_DrawLocs(void)
6038 cl_locnode_t *loc, *nearestloc;
6040 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6041 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6043 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6044 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6048 void R_DrawDebugModel(entity_render_t *ent)
6050 int i, j, k, l, flagsmask;
6051 const int *elements;
6053 msurface_t *surface;
6054 model_t *model = ent->model;
6057 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6059 R_Mesh_ColorPointer(NULL, 0, 0);
6060 R_Mesh_ResetTextureState();
6061 GL_DepthRange(0, 1);
6062 GL_DepthTest(!r_showdisabledepthtest.integer);
6063 GL_DepthMask(false);
6064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6066 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6068 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6069 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6071 if (brush->colbrushf && brush->colbrushf->numtriangles)
6073 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6074 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);
6075 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6078 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6080 if (surface->num_collisiontriangles)
6082 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6083 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);
6084 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6089 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6091 if (r_showtris.integer || r_shownormals.integer)
6093 if (r_showdisabledepthtest.integer)
6095 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6096 GL_DepthMask(false);
6100 GL_BlendFunc(GL_ONE, GL_ZERO);
6103 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6105 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6107 rsurface.texture = surface->texture->currentframe;
6108 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6110 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6111 if (r_showtris.value > 0)
6113 if (!rsurface.texture->currentlayers->depthmask)
6114 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6115 else if (ent == r_refdef.worldentity)
6116 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6118 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6119 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6122 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6124 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6125 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6126 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6127 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6132 if (r_shownormals.value > 0)
6134 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6136 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6138 VectorCopy(rsurface.vertex3f + l * 3, v);
6139 qglVertex3f(v[0], v[1], v[2]);
6140 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6141 qglVertex3f(v[0], v[1], v[2]);
6145 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6147 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6149 VectorCopy(rsurface.vertex3f + l * 3, v);
6150 qglVertex3f(v[0], v[1], v[2]);
6151 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6152 qglVertex3f(v[0], v[1], v[2]);
6156 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6158 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6160 VectorCopy(rsurface.vertex3f + l * 3, v);
6161 qglVertex3f(v[0], v[1], v[2]);
6162 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6163 qglVertex3f(v[0], v[1], v[2]);
6170 rsurface.texture = NULL;
6174 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6175 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6177 int i, j, endj, f, flagsmask;
6178 int counttriangles = 0;
6179 msurface_t *surface, **surfacechain;
6181 model_t *model = r_refdef.worldmodel;
6182 const int maxsurfacelist = 1024;
6183 int numsurfacelist = 0;
6184 msurface_t *surfacelist[1024];
6188 RSurf_ActiveWorldEntity();
6190 // update light styles
6191 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6193 for (i = 0;i < model->brushq1.light_styles;i++)
6195 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6197 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6198 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6199 for (;(surface = *surfacechain);surfacechain++)
6200 surface->cached_dlight = true;
6205 R_UpdateAllTextureInfo(r_refdef.worldentity);
6206 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6210 R_DrawDebugModel(r_refdef.worldentity);
6216 rsurface.uselightmaptexture = false;
6217 rsurface.texture = NULL;
6219 j = model->firstmodelsurface;
6220 endj = j + model->nummodelsurfaces;
6223 // quickly skip over non-visible surfaces
6224 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6226 // quickly iterate over visible surfaces
6227 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6229 // process this surface
6230 surface = model->data_surfaces + j;
6231 // if this surface fits the criteria, add it to the list
6232 if (surface->num_triangles)
6234 // if lightmap parameters changed, rebuild lightmap texture
6235 if (surface->cached_dlight)
6236 R_BuildLightMap(r_refdef.worldentity, surface);
6237 // add face to draw list
6238 surfacelist[numsurfacelist++] = surface;
6239 counttriangles += surface->num_triangles;
6240 if (numsurfacelist >= maxsurfacelist)
6242 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6249 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6250 r_refdef.stats.entities_triangles += counttriangles;
6254 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6256 int i, f, flagsmask;
6257 int counttriangles = 0;
6258 msurface_t *surface, *endsurface, **surfacechain;
6260 model_t *model = ent->model;
6261 const int maxsurfacelist = 1024;
6262 int numsurfacelist = 0;
6263 msurface_t *surfacelist[1024];
6267 // if the model is static it doesn't matter what value we give for
6268 // wantnormals and wanttangents, so this logic uses only rules applicable
6269 // to a model, knowing that they are meaningless otherwise
6270 if (ent == r_refdef.worldentity)
6271 RSurf_ActiveWorldEntity();
6272 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6273 RSurf_ActiveModelEntity(ent, false, false);
6275 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6277 // update light styles
6278 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6280 for (i = 0;i < model->brushq1.light_styles;i++)
6282 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6284 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6285 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6286 for (;(surface = *surfacechain);surfacechain++)
6287 surface->cached_dlight = true;
6292 R_UpdateAllTextureInfo(ent);
6293 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6297 R_DrawDebugModel(ent);
6303 rsurface.uselightmaptexture = false;
6304 rsurface.texture = NULL;
6306 surface = model->data_surfaces + model->firstmodelsurface;
6307 endsurface = surface + model->nummodelsurfaces;
6308 for (;surface < endsurface;surface++)
6310 // if this surface fits the criteria, add it to the list
6311 if (surface->num_triangles)
6313 // if lightmap parameters changed, rebuild lightmap texture
6314 if (surface->cached_dlight)
6315 R_BuildLightMap(ent, surface);
6316 // add face to draw list
6317 surfacelist[numsurfacelist++] = surface;
6318 counttriangles += surface->num_triangles;
6319 if (numsurfacelist >= maxsurfacelist)
6321 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6327 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6328 r_refdef.stats.entities_triangles += counttriangles;