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 unsigned int fogmasktableindex = (unsigned 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 unsigned int fogmasktableindex = (unsigned 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"
755 "# ifdef USESPECULAR\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 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
763 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
765 "# ifdef USEDIFFUSE\n"
766 " // get the surface normal and light normal\n"
767 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
768 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
770 " // calculate directional shading\n"
771 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
773 " color.rgb *= AmbientColor;\n"
777 " color *= myhvec4(gl_Color);\n"
778 "#endif // MODE_LIGHTDIRECTION\n"
783 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
784 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
786 " // get the surface normal and light normal\n"
787 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
789 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
790 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
791 " // calculate directional shading\n"
792 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
793 "# ifdef USESPECULAR\n"
794 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
795 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
798 " // apply lightmap color\n"
799 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
800 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
805 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
806 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
808 " // get the surface normal and light normal\n"
809 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
811 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
812 " // calculate directional shading\n"
813 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
814 "# ifdef USESPECULAR\n"
815 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
816 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
819 " // apply lightmap color\n"
820 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
821 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
826 "#ifdef MODE_LIGHTMAP\n"
827 " // apply lightmap color\n"
828 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
829 "#endif // MODE_LIGHTMAP\n"
839 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
842 "#ifndef MODE_LIGHTSOURCE\n"
843 "# ifdef USEREFLECTION\n"
844 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
845 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
846 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
847 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
853 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
856 "#ifdef USECONTRASTBOOST\n"
857 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
860 " color.rgb *= SceneBrightness;\n"
862 " gl_FragColor = vec4(color);\n"
864 "#endif // MODE_REFRACTION\n"
865 "#endif // MODE_WATER\n"
867 "#endif // FRAGMENT_SHADER\n"
870 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
871 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
872 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
873 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
874 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
875 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
876 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
877 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
878 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
879 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
880 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
882 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
883 const char *shaderpermutationinfo[][2] =
885 {"#define USECOLORMAPPING\n", " colormapping"},
886 {"#define USECONTRASTBOOST\n", " contrastboost"},
887 {"#define USEFOG\n", " fog"},
888 {"#define USECUBEFILTER\n", " cubefilter"},
889 {"#define USEGLOW\n", " glow"},
890 {"#define USEDIFFUSE\n", " diffuse"},
891 {"#define USESPECULAR\n", " specular"},
892 {"#define USEREFLECTION\n", " reflection"},
893 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
894 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
898 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
899 typedef enum shadermode_e
901 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
902 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
903 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
904 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
905 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
906 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
907 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
912 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
913 const char *shadermodeinfo[][2] =
915 {"#define MODE_LIGHTMAP\n", " lightmap"},
916 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
917 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
918 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
919 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
920 {"#define MODE_REFRACTION\n", " refraction"},
921 {"#define MODE_WATER\n", " water"},
925 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
927 typedef struct r_glsl_permutation_s
929 // indicates if we have tried compiling this permutation already
931 // 0 if compilation failed
933 // locations of detected uniforms in program object, or -1 if not found
934 int loc_Texture_Normal;
935 int loc_Texture_Color;
936 int loc_Texture_Gloss;
937 int loc_Texture_Cube;
938 int loc_Texture_Attenuation;
939 int loc_Texture_FogMask;
940 int loc_Texture_Pants;
941 int loc_Texture_Shirt;
942 int loc_Texture_Lightmap;
943 int loc_Texture_Deluxemap;
944 int loc_Texture_Glow;
945 int loc_Texture_Refraction;
946 int loc_Texture_Reflection;
948 int loc_LightPosition;
953 int loc_FogRangeRecip;
954 int loc_AmbientScale;
955 int loc_DiffuseScale;
956 int loc_SpecularScale;
957 int loc_SpecularPower;
959 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
960 int loc_OffsetMapping_Scale;
961 int loc_AmbientColor;
962 int loc_DiffuseColor;
963 int loc_SpecularColor;
965 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
966 int loc_DistortScaleRefractReflect;
967 int loc_ScreenScaleRefractReflect;
968 int loc_ScreenCenterRefractReflect;
969 int loc_RefractColor;
970 int loc_ReflectColor;
971 int loc_ReflectFactor;
972 int loc_ReflectOffset;
974 r_glsl_permutation_t;
976 // information about each possible shader permutation
977 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
978 // currently selected permutation
979 r_glsl_permutation_t *r_glsl_permutation;
981 // these are additional flags used only by R_GLSL_CompilePermutation
982 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
983 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
984 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
986 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
989 qboolean shaderfound;
990 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
991 int vertstrings_count;
992 int geomstrings_count;
993 int fragstrings_count;
995 const char *vertstrings_list[32+1];
996 const char *geomstrings_list[32+1];
997 const char *fragstrings_list[32+1];
998 char permutationname[256];
1003 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1004 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1005 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1006 vertstrings_count = 1;
1007 geomstrings_count = 1;
1008 fragstrings_count = 1;
1009 permutationname[0] = 0;
1010 i = permutation / SHADERPERMUTATION_MODEBASE;
1011 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1012 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1013 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1014 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1015 for (i = 0;shaderpermutationinfo[i][0];i++)
1017 if (permutation & (1<<i))
1019 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1020 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1021 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1022 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1026 // keep line numbers correct
1027 vertstrings_list[vertstrings_count++] = "\n";
1028 geomstrings_list[geomstrings_count++] = "\n";
1029 fragstrings_list[fragstrings_count++] = "\n";
1032 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1033 shaderfound = false;
1036 Con_DPrint("from disk... ");
1037 vertstrings_list[vertstrings_count++] = shaderstring;
1038 geomstrings_list[geomstrings_count++] = shaderstring;
1039 fragstrings_list[fragstrings_count++] = shaderstring;
1042 else if (!strcmp(filename, "glsl/default.glsl"))
1044 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1045 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1046 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1049 // clear any lists that are not needed by this shader
1050 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1051 vertstrings_count = 0;
1052 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1053 geomstrings_count = 0;
1054 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1055 fragstrings_count = 0;
1056 // compile the shader program
1057 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1058 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1062 qglUseProgramObjectARB(p->program);CHECKGLERROR
1063 // look up all the uniform variable names we care about, so we don't
1064 // have to look them up every time we set them
1065 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1066 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1067 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1068 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1069 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1070 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1071 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1072 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1073 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1074 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1075 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1076 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1077 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1078 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1079 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1080 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1081 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1082 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1083 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1084 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1085 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1086 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1087 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1088 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1089 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1090 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1091 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1092 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1093 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1094 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1095 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1096 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1097 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1098 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1099 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1100 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1101 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1102 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1103 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1104 // initialize the samplers to refer to the texture units we use
1105 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1106 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1107 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1108 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1109 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1110 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1111 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1112 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1113 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1114 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1115 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1116 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1117 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1119 qglUseProgramObjectARB(0);CHECKGLERROR
1120 if (developer.integer)
1121 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1125 if (developer.integer)
1126 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1128 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1131 Mem_Free(shaderstring);
1134 void R_GLSL_Restart_f(void)
1137 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1138 if (r_glsl_permutations[i].program)
1139 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1140 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1143 void R_GLSL_DumpShader_f(void)
1147 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1150 Con_Printf("failed to write to glsl/default.glsl\n");
1154 FS_Print(file, "// The engine may define the following macros:\n");
1155 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1156 for (i = 0;shadermodeinfo[i][0];i++)
1157 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1158 for (i = 0;shaderpermutationinfo[i][0];i++)
1159 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1160 FS_Print(file, "\n");
1161 FS_Print(file, builtinshaderstring);
1164 Con_Printf("glsl/default.glsl written\n");
1167 extern rtexture_t *r_shadow_attenuationgradienttexture;
1168 extern rtexture_t *r_shadow_attenuation2dtexture;
1169 extern rtexture_t *r_shadow_attenuation3dtexture;
1170 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1172 // select a permutation of the lighting shader appropriate to this
1173 // combination of texture, entity, light source, and fogging, only use the
1174 // minimum features necessary to avoid wasting rendering time in the
1175 // fragment shader on features that are not being used
1176 const char *shaderfilename = NULL;
1177 unsigned int permutation = 0;
1178 unsigned int shadertype = 0;
1179 shadermode_t mode = 0;
1180 r_glsl_permutation = NULL;
1181 shaderfilename = "glsl/default.glsl";
1182 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1183 // TODO: implement geometry-shader based shadow volumes someday
1184 if (r_glsl_offsetmapping.integer)
1186 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1187 if (r_glsl_offsetmapping_reliefmapping.integer)
1188 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1190 if (rsurfacepass == RSURFPASS_BACKGROUND)
1192 // distorted background
1193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1194 mode = SHADERMODE_WATER;
1196 mode = SHADERMODE_REFRACTION;
1198 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1201 mode = SHADERMODE_LIGHTSOURCE;
1202 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1203 permutation |= SHADERPERMUTATION_CUBEFILTER;
1204 if (diffusescale > 0)
1205 permutation |= SHADERPERMUTATION_DIFFUSE;
1206 if (specularscale > 0)
1207 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1208 if (r_refdef.fogenabled)
1209 permutation |= SHADERPERMUTATION_FOG;
1210 if (rsurface.texture->colormapping)
1211 permutation |= SHADERPERMUTATION_COLORMAPPING;
1212 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1213 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1215 permutation |= SHADERPERMUTATION_REFLECTION;
1217 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1219 // unshaded geometry (fullbright or ambient model lighting)
1220 mode = SHADERMODE_LIGHTMAP;
1221 if (rsurface.texture->currentskinframe->glow)
1222 permutation |= SHADERPERMUTATION_GLOW;
1223 if (r_refdef.fogenabled)
1224 permutation |= SHADERPERMUTATION_FOG;
1225 if (rsurface.texture->colormapping)
1226 permutation |= SHADERPERMUTATION_COLORMAPPING;
1227 if (r_glsl_offsetmapping.integer)
1229 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1230 if (r_glsl_offsetmapping_reliefmapping.integer)
1231 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1233 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1234 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1236 permutation |= SHADERPERMUTATION_REFLECTION;
1238 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1240 // directional model lighting
1241 mode = SHADERMODE_LIGHTDIRECTION;
1242 if (rsurface.texture->currentskinframe->glow)
1243 permutation |= SHADERPERMUTATION_GLOW;
1244 permutation |= SHADERPERMUTATION_DIFFUSE;
1245 if (specularscale > 0)
1246 permutation |= SHADERPERMUTATION_SPECULAR;
1247 if (r_refdef.fogenabled)
1248 permutation |= SHADERPERMUTATION_FOG;
1249 if (rsurface.texture->colormapping)
1250 permutation |= SHADERPERMUTATION_COLORMAPPING;
1251 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1252 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1254 permutation |= SHADERPERMUTATION_REFLECTION;
1256 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1258 // ambient model lighting
1259 mode = SHADERMODE_LIGHTDIRECTION;
1260 if (rsurface.texture->currentskinframe->glow)
1261 permutation |= SHADERPERMUTATION_GLOW;
1262 if (r_refdef.fogenabled)
1263 permutation |= SHADERPERMUTATION_FOG;
1264 if (rsurface.texture->colormapping)
1265 permutation |= SHADERPERMUTATION_COLORMAPPING;
1266 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1267 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1268 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1269 permutation |= SHADERPERMUTATION_REFLECTION;
1274 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1276 // deluxemapping (light direction texture)
1277 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1278 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1280 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1281 if (specularscale > 0)
1282 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1284 else if (r_glsl_deluxemapping.integer >= 2)
1286 // fake deluxemapping (uniform light direction in tangentspace)
1287 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1288 if (specularscale > 0)
1289 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1293 // ordinary lightmapping
1294 mode = SHADERMODE_LIGHTMAP;
1296 if (rsurface.texture->currentskinframe->glow)
1297 permutation |= SHADERPERMUTATION_GLOW;
1298 if (r_refdef.fogenabled)
1299 permutation |= SHADERPERMUTATION_FOG;
1300 if (rsurface.texture->colormapping)
1301 permutation |= SHADERPERMUTATION_COLORMAPPING;
1302 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1303 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1305 permutation |= SHADERPERMUTATION_REFLECTION;
1307 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1308 if (!r_glsl_permutations[permutation].program)
1310 if (!r_glsl_permutations[permutation].compiled)
1311 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1312 if (!r_glsl_permutations[permutation].program)
1314 // remove features until we find a valid permutation
1316 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1320 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");
1321 Cvar_SetValueQuick(&r_glsl, 0);
1322 return 0; // no bit left to clear
1324 // reduce i more quickly whenever it would not remove any bits
1325 if (!(permutation & i))
1328 if (!r_glsl_permutations[permutation].compiled)
1329 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1330 if (r_glsl_permutations[permutation].program)
1335 r_glsl_permutation = r_glsl_permutations + permutation;
1337 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1338 if (mode == SHADERMODE_LIGHTSOURCE)
1340 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1341 if (permutation & SHADERPERMUTATION_DIFFUSE)
1343 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1344 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1345 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1346 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1350 // ambient only is simpler
1351 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1352 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1353 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1354 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1357 else if (mode == SHADERMODE_LIGHTDIRECTION)
1359 if (r_glsl_permutation->loc_AmbientColor >= 0)
1360 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1361 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1362 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1363 if (r_glsl_permutation->loc_SpecularColor >= 0)
1364 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1365 if (r_glsl_permutation->loc_LightDir >= 0)
1366 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1370 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1371 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1372 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1374 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1375 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1377 // The formula used is actually:
1378 // color.rgb *= SceneBrightness;
1379 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1380 // I simplify that to
1381 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1382 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1384 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1385 // and do [[calculations]] here in the engine
1386 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1387 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1390 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1391 if (r_glsl_permutation->loc_FogColor >= 0)
1393 // additive passes are only darkened by fog, not tinted
1394 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1395 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1400 // color.rgb *= SceneBrightness;
1401 VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1402 if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1404 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1405 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1406 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1407 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1409 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1412 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1414 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1415 if (r_glsl_permutation->loc_Color_Pants >= 0)
1417 if (rsurface.texture->currentskinframe->pants)
1418 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1420 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1422 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1424 if (rsurface.texture->currentskinframe->shirt)
1425 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1427 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1429 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1430 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1431 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1432 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);
1433 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]);
1434 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]);
1435 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1436 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1437 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1438 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1443 #define SKINFRAME_HASH 1024
1447 int loadsequence; // incremented each level change
1448 memexpandablearray_t array;
1449 skinframe_t *hash[SKINFRAME_HASH];
1453 void R_SkinFrame_PrepareForPurge(void)
1455 r_skinframe.loadsequence++;
1456 // wrap it without hitting zero
1457 if (r_skinframe.loadsequence >= 200)
1458 r_skinframe.loadsequence = 1;
1461 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1465 // mark the skinframe as used for the purging code
1466 skinframe->loadsequence = r_skinframe.loadsequence;
1469 void R_SkinFrame_Purge(void)
1473 for (i = 0;i < SKINFRAME_HASH;i++)
1475 for (s = r_skinframe.hash[i];s;s = s->next)
1477 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1479 if (s->base == r_texture_notexture) s->base = NULL;
1480 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1481 if (s->merged == s->base) s->merged = NULL;
1482 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1483 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1484 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1485 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1486 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1487 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1488 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1489 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1490 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1491 s->loadsequence = 0;
1497 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1501 char basename[MAX_QPATH];
1503 Image_StripImageExtension(name, basename, sizeof(basename));
1505 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1506 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1507 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1513 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1514 memset(item, 0, sizeof(*item));
1515 strlcpy(item->basename, basename, sizeof(item->basename));
1516 item->textureflags = textureflags;
1517 item->comparewidth = comparewidth;
1518 item->compareheight = compareheight;
1519 item->comparecrc = comparecrc;
1520 item->next = r_skinframe.hash[hashindex];
1521 r_skinframe.hash[hashindex] = item;
1523 R_SkinFrame_MarkUsed(item);
1527 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1529 // FIXME: it should be possible to disable loading various layers using
1530 // cvars, to prevent wasted loading time and memory usage if the user does
1532 qboolean loadnormalmap = true;
1533 qboolean loadgloss = true;
1534 qboolean loadpantsandshirt = true;
1535 qboolean loadglow = true;
1537 unsigned char *pixels;
1538 unsigned char *bumppixels;
1539 unsigned char *basepixels = NULL;
1540 int basepixels_width;
1541 int basepixels_height;
1542 skinframe_t *skinframe;
1544 if (cls.state == ca_dedicated)
1547 // return an existing skinframe if already loaded
1548 // if loading of the first image fails, don't make a new skinframe as it
1549 // would cause all future lookups of this to be missing
1550 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1551 if (skinframe && skinframe->base)
1554 basepixels = loadimagepixels(name, complain, 0, 0, true);
1555 if (basepixels == NULL)
1558 // we've got some pixels to store, so really allocate this new texture now
1560 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1561 skinframe->stain = NULL;
1562 skinframe->merged = NULL;
1563 skinframe->base = r_texture_notexture;
1564 skinframe->pants = NULL;
1565 skinframe->shirt = NULL;
1566 skinframe->nmap = r_texture_blanknormalmap;
1567 skinframe->gloss = NULL;
1568 skinframe->glow = NULL;
1569 skinframe->fog = NULL;
1571 basepixels_width = image_width;
1572 basepixels_height = image_height;
1573 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);
1575 if (textureflags & TEXF_ALPHA)
1577 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1578 if (basepixels[j] < 255)
1580 if (j < basepixels_width * basepixels_height * 4)
1582 // has transparent pixels
1583 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1584 for (j = 0;j < image_width * image_height * 4;j += 4)
1589 pixels[j+3] = basepixels[j+3];
1591 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);
1596 // _norm is the name used by tenebrae and has been adopted as standard
1599 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0, false)) != NULL)
1601 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);
1605 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0, false)) != NULL)
1607 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1608 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1609 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);
1611 Mem_Free(bumppixels);
1613 else if (r_shadow_bumpscale_basetexture.value > 0)
1615 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1616 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1617 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);
1621 // _luma is supported for tenebrae compatibility
1622 // (I think it's a very stupid name, but oh well)
1623 // _glow is the preferred name
1624 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0, false)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1625 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1626 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1627 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1630 Mem_Free(basepixels);
1635 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)
1640 for (i = 0;i < width*height;i++)
1641 if (((unsigned char *)&palette[in[i]])[3] > 0)
1643 if (i == width*height)
1646 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1649 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)
1652 unsigned char *temp1, *temp2;
1653 skinframe_t *skinframe;
1655 if (cls.state == ca_dedicated)
1658 // if already loaded just return it, otherwise make a new skinframe
1659 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1660 if (skinframe && skinframe->base)
1663 skinframe->stain = NULL;
1664 skinframe->merged = NULL;
1665 skinframe->base = r_texture_notexture;
1666 skinframe->pants = NULL;
1667 skinframe->shirt = NULL;
1668 skinframe->nmap = r_texture_blanknormalmap;
1669 skinframe->gloss = NULL;
1670 skinframe->glow = NULL;
1671 skinframe->fog = NULL;
1673 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1677 if (bitsperpixel == 32)
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 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1684 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1687 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1688 if (textureflags & TEXF_ALPHA)
1690 for (i = 3;i < width * height * 4;i += 4)
1691 if (skindata[i] < 255)
1693 if (i < width * height * 4)
1695 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1696 memcpy(fogpixels, skindata, width * height * 4);
1697 for (i = 0;i < width * height * 4;i += 4)
1698 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1699 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1700 Mem_Free(fogpixels);
1704 else if (bitsperpixel == 8)
1706 if (r_shadow_bumpscale_basetexture.value > 0)
1708 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1709 temp2 = temp1 + width * height * 4;
1710 if (bitsperpixel == 32)
1711 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1714 // use either a custom palette or the quake palette
1715 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1716 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1718 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1721 // use either a custom palette, or the quake palette
1722 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
1723 if (!palette && loadglowtexture)
1724 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1725 if (!palette && loadpantsandshirt)
1727 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1728 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1730 if (skinframe->pants || skinframe->shirt)
1731 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1732 if (textureflags & TEXF_ALPHA)
1734 // if not using a custom alphapalette, use the quake one
1736 alphapalette = palette_alpha;
1737 for (i = 0;i < width * height;i++)
1738 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1740 if (i < width * height)
1741 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1748 skinframe_t *R_SkinFrame_LoadMissing(void)
1750 skinframe_t *skinframe;
1752 if (cls.state == ca_dedicated)
1755 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1756 skinframe->stain = NULL;
1757 skinframe->merged = NULL;
1758 skinframe->base = r_texture_notexture;
1759 skinframe->pants = NULL;
1760 skinframe->shirt = NULL;
1761 skinframe->nmap = r_texture_blanknormalmap;
1762 skinframe->gloss = NULL;
1763 skinframe->glow = NULL;
1764 skinframe->fog = NULL;
1769 void gl_main_start(void)
1774 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1775 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1777 alpha = 1 - exp(r / ((double)x*(double)x));
1778 if (x == FOGMASKTABLEWIDTH - 1)
1780 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1783 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1784 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1786 // set up r_skinframe loading system for textures
1787 memset(&r_skinframe, 0, sizeof(r_skinframe));
1788 r_skinframe.loadsequence = 1;
1789 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1791 r_main_texturepool = R_AllocTexturePool();
1792 R_BuildBlankTextures();
1794 if (gl_texturecubemap)
1797 R_BuildNormalizationCube();
1799 R_BuildFogTexture();
1800 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1801 memset(&r_waterstate, 0, sizeof(r_waterstate));
1802 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1803 memset(&r_svbsp, 0, sizeof (r_svbsp));
1806 void gl_main_shutdown(void)
1808 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1809 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1811 // clear out the r_skinframe state
1812 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1813 memset(&r_skinframe, 0, sizeof(r_skinframe));
1816 Mem_Free(r_svbsp.nodes);
1817 memset(&r_svbsp, 0, sizeof (r_svbsp));
1818 R_FreeTexturePool(&r_main_texturepool);
1819 r_texture_blanknormalmap = NULL;
1820 r_texture_white = NULL;
1821 r_texture_grey128 = NULL;
1822 r_texture_black = NULL;
1823 r_texture_whitecube = NULL;
1824 r_texture_normalizationcube = NULL;
1825 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1826 memset(&r_waterstate, 0, sizeof(r_waterstate));
1830 extern void CL_ParseEntityLump(char *entitystring);
1831 void gl_main_newmap(void)
1833 // FIXME: move this code to client
1835 char *entities, entname[MAX_QPATH];
1838 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1839 l = (int)strlen(entname) - 4;
1840 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1842 memcpy(entname + l, ".ent", 5);
1843 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1845 CL_ParseEntityLump(entities);
1850 if (cl.worldmodel->brush.entities)
1851 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1855 void GL_Main_Init(void)
1857 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1859 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1860 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1861 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1862 if (gamemode == GAME_NEHAHRA)
1864 Cvar_RegisterVariable (&gl_fogenable);
1865 Cvar_RegisterVariable (&gl_fogdensity);
1866 Cvar_RegisterVariable (&gl_fogred);
1867 Cvar_RegisterVariable (&gl_foggreen);
1868 Cvar_RegisterVariable (&gl_fogblue);
1869 Cvar_RegisterVariable (&gl_fogstart);
1870 Cvar_RegisterVariable (&gl_fogend);
1872 Cvar_RegisterVariable(&r_depthfirst);
1873 Cvar_RegisterVariable(&r_nearclip);
1874 Cvar_RegisterVariable(&r_showbboxes);
1875 Cvar_RegisterVariable(&r_showsurfaces);
1876 Cvar_RegisterVariable(&r_showtris);
1877 Cvar_RegisterVariable(&r_shownormals);
1878 Cvar_RegisterVariable(&r_showlighting);
1879 Cvar_RegisterVariable(&r_showshadowvolumes);
1880 Cvar_RegisterVariable(&r_showcollisionbrushes);
1881 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1882 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1883 Cvar_RegisterVariable(&r_showdisabledepthtest);
1884 Cvar_RegisterVariable(&r_drawportals);
1885 Cvar_RegisterVariable(&r_drawentities);
1886 Cvar_RegisterVariable(&r_cullentities_trace);
1887 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1888 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1889 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1890 Cvar_RegisterVariable(&r_drawviewmodel);
1891 Cvar_RegisterVariable(&r_speeds);
1892 Cvar_RegisterVariable(&r_fullbrights);
1893 Cvar_RegisterVariable(&r_wateralpha);
1894 Cvar_RegisterVariable(&r_dynamic);
1895 Cvar_RegisterVariable(&r_fullbright);
1896 Cvar_RegisterVariable(&r_shadows);
1897 Cvar_RegisterVariable(&r_shadows_throwdistance);
1898 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1899 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1900 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1901 Cvar_RegisterVariable(&r_textureunits);
1902 Cvar_RegisterVariable(&r_glsl);
1903 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1904 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1905 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1906 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1907 Cvar_RegisterVariable(&r_water);
1908 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1909 Cvar_RegisterVariable(&r_water_clippingplanebias);
1910 Cvar_RegisterVariable(&r_water_refractdistort);
1911 Cvar_RegisterVariable(&r_water_reflectdistort);
1912 Cvar_RegisterVariable(&r_lerpsprites);
1913 Cvar_RegisterVariable(&r_lerpmodels);
1914 Cvar_RegisterVariable(&r_waterscroll);
1915 Cvar_RegisterVariable(&r_bloom);
1916 Cvar_RegisterVariable(&r_bloom_colorscale);
1917 Cvar_RegisterVariable(&r_bloom_brighten);
1918 Cvar_RegisterVariable(&r_bloom_blur);
1919 Cvar_RegisterVariable(&r_bloom_resolution);
1920 Cvar_RegisterVariable(&r_bloom_colorexponent);
1921 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1922 Cvar_RegisterVariable(&r_hdr);
1923 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1924 Cvar_RegisterVariable(&r_glsl_contrastboost);
1925 Cvar_RegisterVariable(&r_hdr_glowintensity);
1926 Cvar_RegisterVariable(&r_hdr_range);
1927 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1928 Cvar_RegisterVariable(&developer_texturelogging);
1929 Cvar_RegisterVariable(&gl_lightmaps);
1930 Cvar_RegisterVariable(&r_test);
1931 Cvar_RegisterVariable(&r_batchmode);
1932 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1933 Cvar_SetValue("r_fullbrights", 0);
1934 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1936 Cvar_RegisterVariable(&r_track_sprites);
1937 Cvar_RegisterVariable(&r_track_sprites_flags);
1938 Cvar_RegisterVariable(&r_track_sprites_scalew);
1939 Cvar_RegisterVariable(&r_track_sprites_scaleh);
1942 extern void R_Textures_Init(void);
1943 extern void GL_Draw_Init(void);
1944 extern void GL_Main_Init(void);
1945 extern void R_Shadow_Init(void);
1946 extern void R_Sky_Init(void);
1947 extern void GL_Surf_Init(void);
1948 extern void R_Light_Init(void);
1949 extern void R_Particles_Init(void);
1950 extern void R_Explosion_Init(void);
1951 extern void gl_backend_init(void);
1952 extern void Sbar_Init(void);
1953 extern void R_LightningBeams_Init(void);
1954 extern void Mod_RenderInit(void);
1956 void Render_Init(void)
1969 R_LightningBeams_Init();
1978 extern char *ENGINE_EXTENSIONS;
1981 VID_CheckExtensions();
1983 // LordHavoc: report supported extensions
1984 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1986 // clear to black (loading plaque will be seen over this)
1988 qglClearColor(0,0,0,1);CHECKGLERROR
1989 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1992 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1996 for (i = 0;i < r_view.numfrustumplanes;i++)
1998 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2001 p = r_view.frustum + i;
2006 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2010 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2014 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2018 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2022 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2026 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2030 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2034 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2042 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2046 for (i = 0;i < numplanes;i++)
2053 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2057 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2061 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2065 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2069 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2073 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2077 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2081 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2089 //==================================================================================
2091 static void R_UpdateEntityLighting(entity_render_t *ent)
2093 vec3_t tempdiffusenormal;
2095 // fetch the lighting from the worldmodel data
2096 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));
2097 VectorClear(ent->modellight_diffuse);
2098 VectorClear(tempdiffusenormal);
2099 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2102 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2103 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2106 VectorSet(ent->modellight_ambient, 1, 1, 1);
2108 // move the light direction into modelspace coordinates for lighting code
2109 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2110 if(VectorLength2(ent->modellight_lightdir) > 0)
2112 VectorNormalize(ent->modellight_lightdir);
2116 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2119 // scale ambient and directional light contributions according to rendering variables
2120 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2121 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2122 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2123 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2124 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2125 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2128 static void R_View_UpdateEntityVisible (void)
2131 entity_render_t *ent;
2133 if (!r_drawentities.integer)
2136 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2137 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2139 // worldmodel can check visibility
2140 for (i = 0;i < r_refdef.numentities;i++)
2142 ent = r_refdef.entities[i];
2143 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));
2146 if(r_cullentities_trace.integer)
2148 for (i = 0;i < r_refdef.numentities;i++)
2150 ent = r_refdef.entities[i];
2151 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2153 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2154 ent->last_trace_visibility = realtime;
2155 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2156 r_viewcache.entityvisible[i] = 0;
2163 // no worldmodel or it can't check visibility
2164 for (i = 0;i < r_refdef.numentities;i++)
2166 ent = r_refdef.entities[i];
2167 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));
2171 // update entity lighting (even on hidden entities for r_shadows)
2172 for (i = 0;i < r_refdef.numentities;i++)
2173 R_UpdateEntityLighting(r_refdef.entities[i]);
2176 // only used if skyrendermasked, and normally returns false
2177 int R_DrawBrushModelsSky (void)
2180 entity_render_t *ent;
2182 if (!r_drawentities.integer)
2186 for (i = 0;i < r_refdef.numentities;i++)
2188 if (!r_viewcache.entityvisible[i])
2190 ent = r_refdef.entities[i];
2191 if (!ent->model || !ent->model->DrawSky)
2193 ent->model->DrawSky(ent);
2199 static void R_DrawNoModel(entity_render_t *ent);
2200 static void R_DrawModels(void)
2203 entity_render_t *ent;
2205 if (!r_drawentities.integer)
2208 for (i = 0;i < r_refdef.numentities;i++)
2210 if (!r_viewcache.entityvisible[i])
2212 ent = r_refdef.entities[i];
2213 r_refdef.stats.entities++;
2214 if (ent->model && ent->model->Draw != NULL)
2215 ent->model->Draw(ent);
2221 static void R_DrawModelsDepth(void)
2224 entity_render_t *ent;
2226 if (!r_drawentities.integer)
2229 for (i = 0;i < r_refdef.numentities;i++)
2231 if (!r_viewcache.entityvisible[i])
2233 ent = r_refdef.entities[i];
2234 if (ent->model && ent->model->DrawDepth != NULL)
2235 ent->model->DrawDepth(ent);
2239 static void R_DrawModelsDebug(void)
2242 entity_render_t *ent;
2244 if (!r_drawentities.integer)
2247 for (i = 0;i < r_refdef.numentities;i++)
2249 if (!r_viewcache.entityvisible[i])
2251 ent = r_refdef.entities[i];
2252 if (ent->model && ent->model->DrawDebug != NULL)
2253 ent->model->DrawDebug(ent);
2257 static void R_DrawModelsAddWaterPlanes(void)
2260 entity_render_t *ent;
2262 if (!r_drawentities.integer)
2265 for (i = 0;i < r_refdef.numentities;i++)
2267 if (!r_viewcache.entityvisible[i])
2269 ent = r_refdef.entities[i];
2270 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2271 ent->model->DrawAddWaterPlanes(ent);
2275 static void R_View_SetFrustum(void)
2278 double slopex, slopey;
2280 // break apart the view matrix into vectors for various purposes
2281 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2282 VectorNegate(r_view.left, r_view.right);
2285 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2286 r_view.frustum[0].normal[1] = 0 - 0;
2287 r_view.frustum[0].normal[2] = -1 - 0;
2288 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2289 r_view.frustum[1].normal[1] = 0 + 0;
2290 r_view.frustum[1].normal[2] = -1 + 0;
2291 r_view.frustum[2].normal[0] = 0 - 0;
2292 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2293 r_view.frustum[2].normal[2] = -1 - 0;
2294 r_view.frustum[3].normal[0] = 0 + 0;
2295 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2296 r_view.frustum[3].normal[2] = -1 + 0;
2300 zNear = r_refdef.nearclip;
2301 nudge = 1.0 - 1.0 / (1<<23);
2302 r_view.frustum[4].normal[0] = 0 - 0;
2303 r_view.frustum[4].normal[1] = 0 - 0;
2304 r_view.frustum[4].normal[2] = -1 - -nudge;
2305 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2306 r_view.frustum[5].normal[0] = 0 + 0;
2307 r_view.frustum[5].normal[1] = 0 + 0;
2308 r_view.frustum[5].normal[2] = -1 + -nudge;
2309 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2315 r_view.frustum[0].normal[0] = m[3] - m[0];
2316 r_view.frustum[0].normal[1] = m[7] - m[4];
2317 r_view.frustum[0].normal[2] = m[11] - m[8];
2318 r_view.frustum[0].dist = m[15] - m[12];
2320 r_view.frustum[1].normal[0] = m[3] + m[0];
2321 r_view.frustum[1].normal[1] = m[7] + m[4];
2322 r_view.frustum[1].normal[2] = m[11] + m[8];
2323 r_view.frustum[1].dist = m[15] + m[12];
2325 r_view.frustum[2].normal[0] = m[3] - m[1];
2326 r_view.frustum[2].normal[1] = m[7] - m[5];
2327 r_view.frustum[2].normal[2] = m[11] - m[9];
2328 r_view.frustum[2].dist = m[15] - m[13];
2330 r_view.frustum[3].normal[0] = m[3] + m[1];
2331 r_view.frustum[3].normal[1] = m[7] + m[5];
2332 r_view.frustum[3].normal[2] = m[11] + m[9];
2333 r_view.frustum[3].dist = m[15] + m[13];
2335 r_view.frustum[4].normal[0] = m[3] - m[2];
2336 r_view.frustum[4].normal[1] = m[7] - m[6];
2337 r_view.frustum[4].normal[2] = m[11] - m[10];
2338 r_view.frustum[4].dist = m[15] - m[14];
2340 r_view.frustum[5].normal[0] = m[3] + m[2];
2341 r_view.frustum[5].normal[1] = m[7] + m[6];
2342 r_view.frustum[5].normal[2] = m[11] + m[10];
2343 r_view.frustum[5].dist = m[15] + m[14];
2346 if (r_view.useperspective)
2348 slopex = 1.0 / r_view.frustum_x;
2349 slopey = 1.0 / r_view.frustum_y;
2350 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2351 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2352 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2353 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2354 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2356 // Leaving those out was a mistake, those were in the old code, and they
2357 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2358 // I couldn't reproduce it after adding those normalizations. --blub
2359 VectorNormalize(r_view.frustum[0].normal);
2360 VectorNormalize(r_view.frustum[1].normal);
2361 VectorNormalize(r_view.frustum[2].normal);
2362 VectorNormalize(r_view.frustum[3].normal);
2364 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2365 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2366 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2367 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2368 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2370 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2371 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2372 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2373 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2374 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2378 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2379 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2380 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2381 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2382 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2383 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2384 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2385 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2386 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2387 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2389 r_view.numfrustumplanes = 5;
2391 if (r_view.useclipplane)
2393 r_view.numfrustumplanes = 6;
2394 r_view.frustum[5] = r_view.clipplane;
2397 for (i = 0;i < r_view.numfrustumplanes;i++)
2398 PlaneClassify(r_view.frustum + i);
2400 // LordHavoc: note to all quake engine coders, Quake had a special case
2401 // for 90 degrees which assumed a square view (wrong), so I removed it,
2402 // Quake2 has it disabled as well.
2404 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2405 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2406 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2407 //PlaneClassify(&frustum[0]);
2409 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2410 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2411 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2412 //PlaneClassify(&frustum[1]);
2414 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2415 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2416 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2417 //PlaneClassify(&frustum[2]);
2419 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2420 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2421 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2422 //PlaneClassify(&frustum[3]);
2425 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2426 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2427 //PlaneClassify(&frustum[4]);
2430 void R_View_Update(void)
2432 R_View_SetFrustum();
2433 R_View_WorldVisibility(r_view.useclipplane);
2434 R_View_UpdateEntityVisible();
2437 void R_SetupView(void)
2439 if (!r_view.useperspective)
2440 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);
2441 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2442 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2444 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2446 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2448 if (r_view.useclipplane)
2450 // LordHavoc: couldn't figure out how to make this approach the
2451 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2452 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2453 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2454 dist = r_view.clipplane.dist;
2455 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2459 void R_ResetViewRendering2D(void)
2461 if (gl_support_fragment_shader)
2463 qglUseProgramObjectARB(0);CHECKGLERROR
2468 // GL is weird because it's bottom to top, r_view.y is top to bottom
2469 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2470 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2471 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2472 GL_Color(1, 1, 1, 1);
2473 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2474 GL_BlendFunc(GL_ONE, GL_ZERO);
2475 GL_AlphaTest(false);
2476 GL_ScissorTest(false);
2477 GL_DepthMask(false);
2478 GL_DepthRange(0, 1);
2479 GL_DepthTest(false);
2480 R_Mesh_Matrix(&identitymatrix);
2481 R_Mesh_ResetTextureState();
2482 GL_PolygonOffset(0, 0);
2483 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2484 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2485 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2486 qglStencilMask(~0);CHECKGLERROR
2487 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2488 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2489 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2492 void R_ResetViewRendering3D(void)
2494 if (gl_support_fragment_shader)
2496 qglUseProgramObjectARB(0);CHECKGLERROR
2501 // GL is weird because it's bottom to top, r_view.y is top to bottom
2502 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2504 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2505 GL_Color(1, 1, 1, 1);
2506 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2507 GL_BlendFunc(GL_ONE, GL_ZERO);
2508 GL_AlphaTest(false);
2509 GL_ScissorTest(true);
2511 GL_DepthRange(0, 1);
2513 R_Mesh_Matrix(&identitymatrix);
2514 R_Mesh_ResetTextureState();
2515 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2516 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2517 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2518 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2519 qglStencilMask(~0);CHECKGLERROR
2520 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2521 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2522 GL_CullFace(r_view.cullface_back);
2526 R_Bloom_SetupShader(
2528 "// written by Forest 'LordHavoc' Hale\n"
2530 "// common definitions between vertex shader and fragment shader:\n"
2532 "#ifdef __GLSL_CG_DATA_TYPES\n"
2533 "#define myhalf half\n"
2534 "#define myhvec2 hvec2\n"
2535 "#define myhvec3 hvec3\n"
2536 "#define myhvec4 hvec4\n"
2538 "#define myhalf float\n"
2539 "#define myhvec2 vec2\n"
2540 "#define myhvec3 vec3\n"
2541 "#define myhvec4 vec4\n"
2544 "varying vec2 ScreenTexCoord;\n"
2545 "varying vec2 BloomTexCoord;\n"
2550 "// vertex shader specific:\n"
2551 "#ifdef VERTEX_SHADER\n"
2555 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2556 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2557 " // transform vertex to camera space, using ftransform to match non-VS\n"
2559 " gl_Position = ftransform();\n"
2562 "#endif // VERTEX_SHADER\n"
2567 "// fragment shader specific:\n"
2568 "#ifdef FRAGMENT_SHADER\n"
2573 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2574 " for (x = -BLUR_X;x <= BLUR_X;x++)
2575 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2576 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2577 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2578 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2580 " gl_FragColor = vec4(color);\n"
2583 "#endif // FRAGMENT_SHADER\n"
2586 void R_RenderScene(qboolean addwaterplanes);
2588 static void R_Water_StartFrame(void)
2591 int waterwidth, waterheight, texturewidth, textureheight;
2592 r_waterstate_waterplane_t *p;
2594 // set waterwidth and waterheight to the water resolution that will be
2595 // used (often less than the screen resolution for faster rendering)
2596 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2597 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2599 // calculate desired texture sizes
2600 // can't use water if the card does not support the texture size
2601 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2602 texturewidth = textureheight = waterwidth = waterheight = 0;
2603 else if (gl_support_arb_texture_non_power_of_two)
2605 texturewidth = waterwidth;
2606 textureheight = waterheight;
2610 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2611 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2614 // allocate textures as needed
2615 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2617 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2618 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2620 if (p->texture_refraction)
2621 R_FreeTexture(p->texture_refraction);
2622 p->texture_refraction = NULL;
2623 if (p->texture_reflection)
2624 R_FreeTexture(p->texture_reflection);
2625 p->texture_reflection = NULL;
2627 memset(&r_waterstate, 0, sizeof(r_waterstate));
2628 r_waterstate.waterwidth = waterwidth;
2629 r_waterstate.waterheight = waterheight;
2630 r_waterstate.texturewidth = texturewidth;
2631 r_waterstate.textureheight = textureheight;
2634 if (r_waterstate.waterwidth)
2636 r_waterstate.enabled = true;
2638 // set up variables that will be used in shader setup
2639 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2640 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2641 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2642 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2645 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2646 r_waterstate.numwaterplanes = 0;
2649 static void R_Water_AddWaterPlane(msurface_t *surface)
2651 int triangleindex, planeindex;
2657 r_waterstate_waterplane_t *p;
2658 // just use the first triangle with a valid normal for any decisions
2659 VectorClear(normal);
2660 VectorClear(center);
2661 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2663 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2664 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2665 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2666 TriangleNormal(vert[0], vert[1], vert[2], normal);
2667 if (VectorLength2(normal) >= 0.001)
2670 // now find the center of this surface
2671 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2673 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2674 VectorAdd(center, vert[0], center);
2676 f = 1.0 / surface->num_triangles*3;
2677 VectorScale(center, f, center);
2679 // find a matching plane if there is one
2680 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2681 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2683 if (planeindex >= r_waterstate.maxwaterplanes)
2684 return; // nothing we can do, out of planes
2686 // if this triangle does not fit any known plane rendered this frame, add one
2687 if (planeindex >= r_waterstate.numwaterplanes)
2689 // store the new plane
2690 r_waterstate.numwaterplanes++;
2691 VectorCopy(normal, p->plane.normal);
2692 VectorNormalize(p->plane.normal);
2693 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2694 PlaneClassify(&p->plane);
2695 // flip the plane if it does not face the viewer
2696 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2698 VectorNegate(p->plane.normal, p->plane.normal);
2699 p->plane.dist *= -1;
2700 PlaneClassify(&p->plane);
2702 // clear materialflags and pvs
2703 p->materialflags = 0;
2704 p->pvsvalid = false;
2706 // merge this surface's materialflags into the waterplane
2707 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2708 // merge this surface's PVS into the waterplane
2709 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2711 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2716 static void R_Water_ProcessPlanes(void)
2718 r_view_t originalview;
2720 r_waterstate_waterplane_t *p;
2722 originalview = r_view;
2724 // make sure enough textures are allocated
2725 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2727 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2729 if (!p->texture_refraction)
2730 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);
2731 if (!p->texture_refraction)
2735 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2737 if (!p->texture_reflection)
2738 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);
2739 if (!p->texture_reflection)
2745 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2747 r_view.showdebug = false;
2748 r_view.width = r_waterstate.waterwidth;
2749 r_view.height = r_waterstate.waterheight;
2750 r_view.useclipplane = true;
2751 r_waterstate.renderingscene = true;
2753 // render the normal view scene and copy into texture
2754 // (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)
2755 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2757 r_view.clipplane = p->plane;
2758 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2759 r_view.clipplane.dist = -r_view.clipplane.dist;
2760 PlaneClassify(&r_view.clipplane);
2762 R_RenderScene(false);
2764 // copy view into the screen texture
2765 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2766 GL_ActiveTexture(0);
2768 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
2771 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2773 // render reflected scene and copy into texture
2774 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2775 r_view.clipplane = p->plane;
2776 // reverse the cullface settings for this render
2777 r_view.cullface_front = GL_FRONT;
2778 r_view.cullface_back = GL_BACK;
2779 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2781 r_view.usecustompvs = true;
2783 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2785 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2788 R_ResetViewRendering3D();
2790 if (r_timereport_active)
2791 R_TimeReport("viewclear");
2793 R_RenderScene(false);
2795 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2796 GL_ActiveTexture(0);
2798 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2800 R_ResetViewRendering3D();
2802 if (r_timereport_active)
2803 R_TimeReport("viewclear");
2806 r_view = originalview;
2807 r_view.clear = true;
2808 r_waterstate.renderingscene = false;
2812 r_view = originalview;
2813 r_waterstate.renderingscene = false;
2814 Cvar_SetValueQuick(&r_water, 0);
2815 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2819 void R_Bloom_StartFrame(void)
2821 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2823 // set bloomwidth and bloomheight to the bloom resolution that will be
2824 // used (often less than the screen resolution for faster rendering)
2825 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2826 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2827 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2829 // calculate desired texture sizes
2830 if (gl_support_arb_texture_non_power_of_two)
2832 screentexturewidth = r_view.width;
2833 screentextureheight = r_view.height;
2834 bloomtexturewidth = r_bloomstate.bloomwidth;
2835 bloomtextureheight = r_bloomstate.bloomheight;
2839 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2840 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2841 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2842 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2847 screentexturewidth = screentextureheight = 0;
2849 else if (r_bloom.integer)
2854 screentexturewidth = screentextureheight = 0;
2855 bloomtexturewidth = bloomtextureheight = 0;
2858 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)
2860 // can't use bloom if the parameters are too weird
2861 // can't use bloom if the card does not support the texture size
2862 if (r_bloomstate.texture_screen)
2863 R_FreeTexture(r_bloomstate.texture_screen);
2864 if (r_bloomstate.texture_bloom)
2865 R_FreeTexture(r_bloomstate.texture_bloom);
2866 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2870 r_bloomstate.enabled = true;
2871 r_bloomstate.hdr = r_hdr.integer != 0;
2873 // allocate textures as needed
2874 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2876 if (r_bloomstate.texture_screen)
2877 R_FreeTexture(r_bloomstate.texture_screen);
2878 r_bloomstate.texture_screen = NULL;
2879 r_bloomstate.screentexturewidth = screentexturewidth;
2880 r_bloomstate.screentextureheight = screentextureheight;
2881 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2882 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);
2884 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2886 if (r_bloomstate.texture_bloom)
2887 R_FreeTexture(r_bloomstate.texture_bloom);
2888 r_bloomstate.texture_bloom = NULL;
2889 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2890 r_bloomstate.bloomtextureheight = bloomtextureheight;
2891 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2892 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);
2895 // set up a texcoord array for the full resolution screen image
2896 // (we have to keep this around to copy back during final render)
2897 r_bloomstate.screentexcoord2f[0] = 0;
2898 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2899 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2900 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2901 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2902 r_bloomstate.screentexcoord2f[5] = 0;
2903 r_bloomstate.screentexcoord2f[6] = 0;
2904 r_bloomstate.screentexcoord2f[7] = 0;
2906 // set up a texcoord array for the reduced resolution bloom image
2907 // (which will be additive blended over the screen image)
2908 r_bloomstate.bloomtexcoord2f[0] = 0;
2909 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2910 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2911 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2912 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2913 r_bloomstate.bloomtexcoord2f[5] = 0;
2914 r_bloomstate.bloomtexcoord2f[6] = 0;
2915 r_bloomstate.bloomtexcoord2f[7] = 0;
2918 void R_Bloom_CopyScreenTexture(float colorscale)
2920 r_refdef.stats.bloom++;
2922 R_ResetViewRendering2D();
2923 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2924 R_Mesh_ColorPointer(NULL, 0, 0);
2925 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2926 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2928 // copy view into the screen texture
2929 GL_ActiveTexture(0);
2931 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
2932 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2934 // now scale it down to the bloom texture size
2936 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2937 GL_BlendFunc(GL_ONE, GL_ZERO);
2938 GL_Color(colorscale, colorscale, colorscale, 1);
2939 // TODO: optimize with multitexture or GLSL
2940 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2941 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2943 // we now have a bloom image in the framebuffer
2944 // copy it into the bloom image texture for later processing
2945 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2946 GL_ActiveTexture(0);
2948 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
2949 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2952 void R_Bloom_CopyHDRTexture(void)
2954 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2955 GL_ActiveTexture(0);
2957 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
2958 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2961 void R_Bloom_MakeTexture(void)
2964 float xoffset, yoffset, r, brighten;
2966 r_refdef.stats.bloom++;
2968 R_ResetViewRendering2D();
2969 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2970 R_Mesh_ColorPointer(NULL, 0, 0);
2972 // we have a bloom image in the framebuffer
2974 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2976 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2979 r = bound(0, r_bloom_colorexponent.value / x, 1);
2980 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2981 GL_Color(r, r, r, 1);
2982 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2983 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2984 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2985 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2987 // copy the vertically blurred bloom view to a texture
2988 GL_ActiveTexture(0);
2990 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
2991 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2994 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2995 brighten = r_bloom_brighten.value;
2997 brighten *= r_hdr_range.value;
2998 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2999 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3001 for (dir = 0;dir < 2;dir++)
3003 // blend on at multiple vertical offsets to achieve a vertical blur
3004 // TODO: do offset blends using GLSL
3005 GL_BlendFunc(GL_ONE, GL_ZERO);
3006 for (x = -range;x <= range;x++)
3008 if (!dir){xoffset = 0;yoffset = x;}
3009 else {xoffset = x;yoffset = 0;}
3010 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3011 yoffset /= (float)r_bloomstate.bloomtextureheight;
3012 // compute a texcoord array with the specified x and y offset
3013 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3014 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3015 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3016 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3017 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3018 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3019 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3020 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3021 // this r value looks like a 'dot' particle, fading sharply to
3022 // black at the edges
3023 // (probably not realistic but looks good enough)
3024 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3025 //r = (dir ? 1.0f : brighten)/(range*2+1);
3026 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3027 GL_Color(r, r, r, 1);
3028 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3029 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3030 GL_BlendFunc(GL_ONE, GL_ONE);
3033 // copy the vertically blurred bloom view to a texture
3034 GL_ActiveTexture(0);
3036 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
3037 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3040 // apply subtract last
3041 // (just like it would be in a GLSL shader)
3042 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3044 GL_BlendFunc(GL_ONE, GL_ZERO);
3045 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3046 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3047 GL_Color(1, 1, 1, 1);
3048 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3049 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3051 GL_BlendFunc(GL_ONE, GL_ONE);
3052 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3053 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3054 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3055 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3056 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3057 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3058 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3060 // copy the darkened bloom view to a texture
3061 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3062 GL_ActiveTexture(0);
3064 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
3065 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3069 void R_HDR_RenderBloomTexture(void)
3071 int oldwidth, oldheight;
3073 oldwidth = r_view.width;
3074 oldheight = r_view.height;
3075 r_view.width = r_bloomstate.bloomwidth;
3076 r_view.height = r_bloomstate.bloomheight;
3078 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3079 // TODO: add exposure compensation features
3080 // TODO: add fp16 framebuffer support
3082 r_view.showdebug = false;
3083 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3085 r_view.colorscale /= r_hdr_range.value;
3086 r_waterstate.numwaterplanes = 0;
3087 R_RenderScene(r_waterstate.enabled);
3088 r_view.showdebug = true;
3090 R_ResetViewRendering2D();
3092 R_Bloom_CopyHDRTexture();
3093 R_Bloom_MakeTexture();
3095 R_ResetViewRendering3D();
3098 if (r_timereport_active)
3099 R_TimeReport("viewclear");
3101 // restore the view settings
3102 r_view.width = oldwidth;
3103 r_view.height = oldheight;
3106 static void R_BlendView(void)
3108 if (r_bloomstate.enabled && r_bloomstate.hdr)
3110 // render high dynamic range bloom effect
3111 // the bloom texture was made earlier this render, so we just need to
3112 // blend it onto the screen...
3113 R_ResetViewRendering2D();
3114 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3115 R_Mesh_ColorPointer(NULL, 0, 0);
3116 GL_Color(1, 1, 1, 1);
3117 GL_BlendFunc(GL_ONE, GL_ONE);
3118 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3119 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3120 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3121 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3123 else if (r_bloomstate.enabled)
3125 // render simple bloom effect
3126 // copy the screen and shrink it and darken it for the bloom process
3127 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3128 // make the bloom texture
3129 R_Bloom_MakeTexture();
3130 // put the original screen image back in place and blend the bloom
3132 R_ResetViewRendering2D();
3133 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3134 R_Mesh_ColorPointer(NULL, 0, 0);
3135 GL_Color(1, 1, 1, 1);
3136 GL_BlendFunc(GL_ONE, GL_ZERO);
3137 // do both in one pass if possible
3138 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3139 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3140 if (r_textureunits.integer >= 2 && gl_combine.integer)
3142 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3143 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3144 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3148 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3149 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3150 // now blend on the bloom texture
3151 GL_BlendFunc(GL_ONE, GL_ONE);
3152 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3153 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3155 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3156 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3158 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3160 // apply a color tint to the whole view
3161 R_ResetViewRendering2D();
3162 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3163 R_Mesh_ColorPointer(NULL, 0, 0);
3164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3165 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3166 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3170 void R_RenderScene(qboolean addwaterplanes);
3172 matrix4x4_t r_waterscrollmatrix;
3174 void R_UpdateVariables(void)
3178 r_refdef.farclip = 4096;
3179 if (r_refdef.worldmodel)
3180 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3181 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3183 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3184 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3185 r_refdef.polygonfactor = 0;
3186 r_refdef.polygonoffset = 0;
3187 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3188 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3190 r_refdef.rtworld = r_shadow_realtime_world.integer;
3191 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3192 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3193 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3194 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3195 if (r_showsurfaces.integer)
3197 r_refdef.rtworld = false;
3198 r_refdef.rtworldshadows = false;
3199 r_refdef.rtdlight = false;
3200 r_refdef.rtdlightshadows = false;
3201 r_refdef.lightmapintensity = 0;
3204 if (gamemode == GAME_NEHAHRA)
3206 if (gl_fogenable.integer)
3208 r_refdef.oldgl_fogenable = true;
3209 r_refdef.fog_density = gl_fogdensity.value;
3210 r_refdef.fog_red = gl_fogred.value;
3211 r_refdef.fog_green = gl_foggreen.value;
3212 r_refdef.fog_blue = gl_fogblue.value;
3214 else if (r_refdef.oldgl_fogenable)
3216 r_refdef.oldgl_fogenable = false;
3217 r_refdef.fog_density = 0;
3218 r_refdef.fog_red = 0;
3219 r_refdef.fog_green = 0;
3220 r_refdef.fog_blue = 0;
3223 if (r_refdef.fog_density)
3225 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3226 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3227 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3229 if (r_refdef.fog_density)
3231 r_refdef.fogenabled = true;
3232 // this is the point where the fog reaches 0.9986 alpha, which we
3233 // consider a good enough cutoff point for the texture
3234 // (0.9986 * 256 == 255.6)
3235 r_refdef.fogrange = 400 / r_refdef.fog_density;
3236 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3237 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3238 // fog color was already set
3241 r_refdef.fogenabled = false;
3249 void R_RenderView(void)
3251 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3252 return; //Host_Error ("R_RenderView: NULL worldmodel");
3254 R_Shadow_UpdateWorldLightSelection();
3256 R_Bloom_StartFrame();
3257 R_Water_StartFrame();
3260 if (r_timereport_active)
3261 R_TimeReport("viewsetup");
3263 R_ResetViewRendering3D();
3268 if (r_timereport_active)
3269 R_TimeReport("viewclear");
3271 r_view.clear = true;
3273 r_view.showdebug = true;
3275 // this produces a bloom texture to be used in R_BlendView() later
3277 R_HDR_RenderBloomTexture();
3279 r_view.colorscale = r_hdr_scenebrightness.value;
3280 r_waterstate.numwaterplanes = 0;
3281 R_RenderScene(r_waterstate.enabled);
3284 if (r_timereport_active)
3285 R_TimeReport("blendview");
3287 GL_Scissor(0, 0, vid.width, vid.height);
3288 GL_ScissorTest(false);
3292 extern void R_DrawLightningBeams (void);
3293 extern void VM_CL_AddPolygonsToMeshQueue (void);
3294 extern void R_DrawPortals (void);
3295 extern cvar_t cl_locs_show;
3296 static void R_DrawLocs(void);
3297 static void R_DrawEntityBBoxes(void);
3298 void R_RenderScene(qboolean addwaterplanes)
3302 R_ResetViewRendering3D();
3305 if (r_timereport_active)
3306 R_TimeReport("watervis");
3308 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3310 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3311 if (r_timereport_active)
3312 R_TimeReport("waterworld");
3315 // don't let sound skip if going slow
3316 if (r_refdef.extraupdate)
3319 R_DrawModelsAddWaterPlanes();
3320 if (r_timereport_active)
3321 R_TimeReport("watermodels");
3323 R_Water_ProcessPlanes();
3324 if (r_timereport_active)
3325 R_TimeReport("waterscenes");
3328 R_ResetViewRendering3D();
3330 // don't let sound skip if going slow
3331 if (r_refdef.extraupdate)
3334 R_MeshQueue_BeginScene();
3339 if (r_timereport_active)
3340 R_TimeReport("visibility");
3342 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);
3344 if (cl.csqc_vidvars.drawworld)
3346 // don't let sound skip if going slow
3347 if (r_refdef.extraupdate)
3350 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3352 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3353 if (r_timereport_active)
3354 R_TimeReport("worldsky");
3357 if (R_DrawBrushModelsSky() && r_timereport_active)
3358 R_TimeReport("bmodelsky");
3361 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3363 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3364 if (r_timereport_active)
3365 R_TimeReport("worlddepth");
3367 if (r_depthfirst.integer >= 2)
3369 R_DrawModelsDepth();
3370 if (r_timereport_active)
3371 R_TimeReport("modeldepth");
3374 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3376 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3377 if (r_timereport_active)
3378 R_TimeReport("world");
3381 // don't let sound skip if going slow
3382 if (r_refdef.extraupdate)
3386 if (r_timereport_active)
3387 R_TimeReport("models");
3389 // don't let sound skip if going slow
3390 if (r_refdef.extraupdate)
3393 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3395 R_DrawModelShadows();
3397 R_ResetViewRendering3D();
3399 // don't let sound skip if going slow
3400 if (r_refdef.extraupdate)
3404 R_ShadowVolumeLighting(false);
3405 if (r_timereport_active)
3406 R_TimeReport("rtlights");
3408 // don't let sound skip if going slow
3409 if (r_refdef.extraupdate)
3412 if (cl.csqc_vidvars.drawworld)
3414 R_DrawLightningBeams();
3415 if (r_timereport_active)
3416 R_TimeReport("lightning");
3419 if (r_timereport_active)
3420 R_TimeReport("decals");
3423 if (r_timereport_active)
3424 R_TimeReport("particles");
3427 if (r_timereport_active)
3428 R_TimeReport("explosions");
3431 if (gl_support_fragment_shader)
3433 qglUseProgramObjectARB(0);CHECKGLERROR
3435 VM_CL_AddPolygonsToMeshQueue();
3437 if (r_view.showdebug)
3439 if (cl_locs_show.integer)
3442 if (r_timereport_active)
3443 R_TimeReport("showlocs");
3446 if (r_drawportals.integer)
3449 if (r_timereport_active)
3450 R_TimeReport("portals");
3453 if (r_showbboxes.value > 0)
3455 R_DrawEntityBBoxes();
3456 if (r_timereport_active)
3457 R_TimeReport("bboxes");
3461 if (gl_support_fragment_shader)
3463 qglUseProgramObjectARB(0);CHECKGLERROR
3465 R_MeshQueue_RenderTransparent();
3466 if (r_timereport_active)
3467 R_TimeReport("drawtrans");
3469 if (gl_support_fragment_shader)
3471 qglUseProgramObjectARB(0);CHECKGLERROR
3474 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3476 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3477 if (r_timereport_active)
3478 R_TimeReport("worlddebug");
3479 R_DrawModelsDebug();
3480 if (r_timereport_active)
3481 R_TimeReport("modeldebug");
3484 if (gl_support_fragment_shader)
3486 qglUseProgramObjectARB(0);CHECKGLERROR
3489 if (cl.csqc_vidvars.drawworld)
3492 if (r_timereport_active)
3493 R_TimeReport("coronas");
3496 // don't let sound skip if going slow
3497 if (r_refdef.extraupdate)
3500 R_ResetViewRendering2D();
3503 static const int bboxelements[36] =
3513 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3516 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3517 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3518 GL_DepthMask(false);
3519 GL_DepthRange(0, 1);
3520 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3521 R_Mesh_Matrix(&identitymatrix);
3522 R_Mesh_ResetTextureState();
3524 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3525 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3526 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3527 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3528 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3529 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3530 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3531 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3532 R_FillColors(color4f, 8, cr, cg, cb, ca);
3533 if (r_refdef.fogenabled)
3535 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3537 f1 = FogPoint_World(v);
3539 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3540 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3541 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3544 R_Mesh_VertexPointer(vertex3f, 0, 0);
3545 R_Mesh_ColorPointer(color4f, 0, 0);
3546 R_Mesh_ResetTextureState();
3547 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3550 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3554 prvm_edict_t *edict;
3555 // this function draws bounding boxes of server entities
3559 for (i = 0;i < numsurfaces;i++)
3561 edict = PRVM_EDICT_NUM(surfacelist[i]);
3562 switch ((int)edict->fields.server->solid)
3564 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3565 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3566 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3567 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3568 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3569 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3571 color[3] *= r_showbboxes.value;
3572 color[3] = bound(0, color[3], 1);
3573 GL_DepthTest(!r_showdisabledepthtest.integer);
3574 GL_CullFace(r_view.cullface_front);
3575 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3580 static void R_DrawEntityBBoxes(void)
3583 prvm_edict_t *edict;
3585 // this function draws bounding boxes of server entities
3589 for (i = 0;i < prog->num_edicts;i++)
3591 edict = PRVM_EDICT_NUM(i);
3592 if (edict->priv.server->free)
3594 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3595 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3600 int nomodelelements[24] =
3612 float nomodelvertex3f[6*3] =
3622 float nomodelcolor4f[6*4] =
3624 0.0f, 0.0f, 0.5f, 1.0f,
3625 0.0f, 0.0f, 0.5f, 1.0f,
3626 0.0f, 0.5f, 0.0f, 1.0f,
3627 0.0f, 0.5f, 0.0f, 1.0f,
3628 0.5f, 0.0f, 0.0f, 1.0f,
3629 0.5f, 0.0f, 0.0f, 1.0f
3632 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3637 // this is only called once per entity so numsurfaces is always 1, and
3638 // surfacelist is always {0}, so this code does not handle batches
3639 R_Mesh_Matrix(&ent->matrix);
3641 if (ent->flags & EF_ADDITIVE)
3643 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3644 GL_DepthMask(false);
3646 else if (ent->alpha < 1)
3648 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3649 GL_DepthMask(false);
3653 GL_BlendFunc(GL_ONE, GL_ZERO);
3656 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3657 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3658 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3659 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3660 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3661 if (r_refdef.fogenabled)
3664 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3665 R_Mesh_ColorPointer(color4f, 0, 0);
3666 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3667 f1 = FogPoint_World(org);
3669 for (i = 0, c = color4f;i < 6;i++, c += 4)
3671 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3672 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3673 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3677 else if (ent->alpha != 1)
3679 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3680 R_Mesh_ColorPointer(color4f, 0, 0);
3681 for (i = 0, c = color4f;i < 6;i++, c += 4)
3685 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3686 R_Mesh_ResetTextureState();
3687 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3690 void R_DrawNoModel(entity_render_t *ent)
3693 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3694 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3695 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3697 // R_DrawNoModelCallback(ent, 0);
3700 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3702 vec3_t right1, right2, diff, normal;
3704 VectorSubtract (org2, org1, normal);
3706 // calculate 'right' vector for start
3707 VectorSubtract (r_view.origin, org1, diff);
3708 CrossProduct (normal, diff, right1);
3709 VectorNormalize (right1);
3711 // calculate 'right' vector for end
3712 VectorSubtract (r_view.origin, org2, diff);
3713 CrossProduct (normal, diff, right2);
3714 VectorNormalize (right2);
3716 vert[ 0] = org1[0] + width * right1[0];
3717 vert[ 1] = org1[1] + width * right1[1];
3718 vert[ 2] = org1[2] + width * right1[2];
3719 vert[ 3] = org1[0] - width * right1[0];
3720 vert[ 4] = org1[1] - width * right1[1];
3721 vert[ 5] = org1[2] - width * right1[2];
3722 vert[ 6] = org2[0] - width * right2[0];
3723 vert[ 7] = org2[1] - width * right2[1];
3724 vert[ 8] = org2[2] - width * right2[2];
3725 vert[ 9] = org2[0] + width * right2[0];
3726 vert[10] = org2[1] + width * right2[1];
3727 vert[11] = org2[2] + width * right2[2];
3730 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3732 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)
3737 if (r_refdef.fogenabled)
3738 fog = FogPoint_World(origin);
3740 R_Mesh_Matrix(&identitymatrix);
3741 GL_BlendFunc(blendfunc1, blendfunc2);
3747 GL_CullFace(r_view.cullface_front);
3750 GL_CullFace(r_view.cullface_back);
3752 GL_DepthMask(false);
3753 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3754 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3755 GL_DepthTest(!depthdisable);
3757 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3758 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3759 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3760 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3761 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3762 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3763 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3764 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3765 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3766 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3767 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3768 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3770 R_Mesh_VertexPointer(vertex3f, 0, 0);
3771 R_Mesh_ColorPointer(NULL, 0, 0);
3772 R_Mesh_ResetTextureState();
3773 R_Mesh_TexBind(0, R_GetTexture(texture));
3774 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3775 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3776 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3777 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3779 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3781 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3782 GL_BlendFunc(blendfunc1, GL_ONE);
3784 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);
3785 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3789 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3794 VectorSet(v, x, y, z);
3795 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3796 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3798 if (i == mesh->numvertices)
3800 if (mesh->numvertices < mesh->maxvertices)
3802 VectorCopy(v, vertex3f);
3803 mesh->numvertices++;
3805 return mesh->numvertices;
3811 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3815 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3816 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3817 e = mesh->element3i + mesh->numtriangles * 3;
3818 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3820 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3821 if (mesh->numtriangles < mesh->maxtriangles)
3826 mesh->numtriangles++;
3828 element[1] = element[2];
3832 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3836 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3837 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3838 e = mesh->element3i + mesh->numtriangles * 3;
3839 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3841 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3842 if (mesh->numtriangles < mesh->maxtriangles)
3847 mesh->numtriangles++;
3849 element[1] = element[2];
3853 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3854 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3856 int planenum, planenum2;
3859 mplane_t *plane, *plane2;
3861 double temppoints[2][256*3];
3862 // figure out how large a bounding box we need to properly compute this brush
3864 for (w = 0;w < numplanes;w++)
3865 maxdist = max(maxdist, planes[w].dist);
3866 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3867 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3868 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3872 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3873 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3875 if (planenum2 == planenum)
3877 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);
3880 if (tempnumpoints < 3)
3882 // generate elements forming a triangle fan for this polygon
3883 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3887 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)
3889 texturelayer_t *layer;
3890 layer = t->currentlayers + t->currentnumlayers++;
3892 layer->depthmask = depthmask;
3893 layer->blendfunc1 = blendfunc1;
3894 layer->blendfunc2 = blendfunc2;
3895 layer->texture = texture;
3896 layer->texmatrix = *matrix;
3897 layer->color[0] = r * r_view.colorscale;
3898 layer->color[1] = g * r_view.colorscale;
3899 layer->color[2] = b * r_view.colorscale;
3900 layer->color[3] = a;
3903 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3906 index = parms[2] + r_refdef.time * parms[3];
3907 index -= floor(index);
3911 case Q3WAVEFUNC_NONE:
3912 case Q3WAVEFUNC_NOISE:
3913 case Q3WAVEFUNC_COUNT:
3916 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3917 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3918 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3919 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3920 case Q3WAVEFUNC_TRIANGLE:
3922 f = index - floor(index);
3933 return (float)(parms[0] + parms[1] * f);
3936 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3939 model_t *model = ent->model;
3942 q3shaderinfo_layer_tcmod_t *tcmod;
3944 // switch to an alternate material if this is a q1bsp animated material
3946 texture_t *texture = t;
3947 int s = ent->skinnum;
3948 if ((unsigned int)s >= (unsigned int)model->numskins)
3950 if (model->skinscenes)
3952 if (model->skinscenes[s].framecount > 1)
3953 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3955 s = model->skinscenes[s].firstframe;
3958 t = t + s * model->num_surfaces;
3961 // use an alternate animation if the entity's frame is not 0,
3962 // and only if the texture has an alternate animation
3963 if (ent->frame2 != 0 && t->anim_total[1])
3964 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3966 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3968 texture->currentframe = t;
3971 // update currentskinframe to be a qw skin or animation frame
3972 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3974 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3976 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3977 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3978 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);
3980 t->currentskinframe = r_qwskincache_skinframe[i];
3981 if (t->currentskinframe == NULL)
3982 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3984 else if (t->numskinframes >= 2)
3985 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3986 if (t->backgroundnumskinframes >= 2)
3987 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3989 t->currentmaterialflags = t->basematerialflags;
3990 t->currentalpha = ent->alpha;
3991 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3993 t->currentalpha *= r_wateralpha.value;
3995 * FIXME what is this supposed to do?
3996 // if rendering refraction/reflection, disable transparency
3997 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3998 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4001 if(!r_waterstate.enabled)
4002 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4003 if (!(ent->flags & RENDER_LIGHT))
4004 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4005 else if (rsurface.modeltexcoordlightmap2f == NULL)
4007 // pick a model lighting mode
4008 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4009 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4011 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4013 if (ent->effects & EF_ADDITIVE)
4014 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4015 else if (t->currentalpha < 1)
4016 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4017 if (ent->effects & EF_DOUBLESIDED)
4018 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4019 if (ent->effects & EF_NODEPTHTEST)
4020 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4021 if (ent->flags & RENDER_VIEWMODEL)
4022 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4023 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4024 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4026 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
4029 switch(tcmod->tcmod)
4033 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4034 matrix = r_waterscrollmatrix;
4036 matrix = identitymatrix;
4038 case Q3TCMOD_ENTITYTRANSLATE:
4039 // this is used in Q3 to allow the gamecode to control texcoord
4040 // scrolling on the entity, which is not supported in darkplaces yet.
4041 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4043 case Q3TCMOD_ROTATE:
4044 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4045 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4046 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4049 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4051 case Q3TCMOD_SCROLL:
4052 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4054 case Q3TCMOD_STRETCH:
4055 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4056 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4058 case Q3TCMOD_TRANSFORM:
4059 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4060 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4061 VectorSet(tcmat + 6, 0 , 0 , 1);
4062 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4063 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4065 case Q3TCMOD_TURBULENT:
4066 // this is handled in the RSurf_PrepareVertices function
4067 matrix = identitymatrix;
4070 // either replace or concatenate the transformation
4072 t->currenttexmatrix = matrix;
4075 matrix4x4_t temp = t->currenttexmatrix;
4076 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4080 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4081 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4082 t->glosstexture = r_texture_black;
4083 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4084 t->backgroundglosstexture = r_texture_black;
4085 t->specularpower = r_shadow_glossexponent.value;
4086 // TODO: store reference values for these in the texture?
4087 t->specularscale = 0;
4088 if (r_shadow_gloss.integer > 0)
4090 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4092 if (r_shadow_glossintensity.value > 0)
4094 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4095 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4096 t->specularscale = r_shadow_glossintensity.value;
4099 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4101 t->glosstexture = r_texture_white;
4102 t->backgroundglosstexture = r_texture_white;
4103 t->specularscale = r_shadow_gloss2intensity.value;
4107 // lightmaps mode looks bad with dlights using actual texturing, so turn
4108 // off the colormap and glossmap, but leave the normalmap on as it still
4109 // accurately represents the shading involved
4110 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4112 t->basetexture = r_texture_white;
4113 t->specularscale = 0;
4116 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4117 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4118 // submodels are biased to avoid z-fighting with world surfaces that they
4119 // may be exactly overlapping (avoids z-fighting artifacts on certain
4120 // doors and things in Quake maps)
4121 if (ent->model->brush.submodel)
4123 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4124 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4127 VectorClear(t->dlightcolor);
4128 t->currentnumlayers = 0;
4129 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4131 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4133 int blendfunc1, blendfunc2, depthmask;
4134 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4136 blendfunc1 = GL_SRC_ALPHA;
4137 blendfunc2 = GL_ONE;
4139 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4141 blendfunc1 = GL_SRC_ALPHA;
4142 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4144 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4146 blendfunc1 = t->customblendfunc[0];
4147 blendfunc2 = t->customblendfunc[1];
4151 blendfunc1 = GL_ONE;
4152 blendfunc2 = GL_ZERO;
4154 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4155 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4157 rtexture_t *currentbasetexture;
4159 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4160 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4161 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4162 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4164 // fullbright is not affected by r_refdef.lightmapintensity
4165 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4166 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4167 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);
4168 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4169 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);
4174 // set the color tint used for lights affecting this surface
4175 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4177 // q3bsp has no lightmap updates, so the lightstylevalue that
4178 // would normally be baked into the lightmap must be
4179 // applied to the color
4180 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4181 if (ent->model->type == mod_brushq3)
4182 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4183 colorscale *= r_refdef.lightmapintensity;
4184 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);
4185 if (r_ambient.value >= (1.0f/64.0f))
4186 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);
4187 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4189 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);
4190 if (r_ambient.value >= (1.0f/64.0f))
4191 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);
4193 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4195 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);
4196 if (r_ambient.value >= (1.0f/64.0f))
4197 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);
4200 if (t->currentskinframe->glow != NULL)
4201 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);
4202 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4204 // if this is opaque use alpha blend which will darken the earlier
4207 // if this is an alpha blended material, all the earlier passes
4208 // were darkened by fog already, so we only need to add the fog
4209 // color ontop through the fog mask texture
4211 // if this is an additive blended material, all the earlier passes
4212 // were darkened by fog already, and we should not add fog color
4213 // (because the background was not darkened, there is no fog color
4214 // that was lost behind it).
4215 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);
4222 void R_UpdateAllTextureInfo(entity_render_t *ent)
4226 for (i = 0;i < ent->model->num_texturesperskin;i++)
4227 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4230 rsurfacestate_t rsurface;
4232 void R_Mesh_ResizeArrays(int newvertices)
4235 if (rsurface.array_size >= newvertices)
4237 if (rsurface.array_modelvertex3f)
4238 Mem_Free(rsurface.array_modelvertex3f);
4239 rsurface.array_size = (newvertices + 1023) & ~1023;
4240 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4241 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4242 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4243 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4244 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4245 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4246 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4247 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4248 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4249 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4250 rsurface.array_color4f = base + rsurface.array_size * 27;
4251 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4254 void RSurf_CleanUp(void)
4257 if (rsurface.mode == RSURFMODE_GLSL)
4259 qglUseProgramObjectARB(0);CHECKGLERROR
4261 GL_AlphaTest(false);
4262 rsurface.mode = RSURFMODE_NONE;
4263 rsurface.uselightmaptexture = false;
4264 rsurface.texture = NULL;
4267 void RSurf_ActiveWorldEntity(void)
4269 model_t *model = r_refdef.worldmodel;
4271 if (rsurface.array_size < model->surfmesh.num_vertices)
4272 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4273 rsurface.matrix = identitymatrix;
4274 rsurface.inversematrix = identitymatrix;
4275 R_Mesh_Matrix(&identitymatrix);
4276 VectorCopy(r_view.origin, rsurface.modelorg);
4277 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4278 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4279 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4280 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4281 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4282 rsurface.frameblend[0].frame = 0;
4283 rsurface.frameblend[0].lerp = 1;
4284 rsurface.frameblend[1].frame = 0;
4285 rsurface.frameblend[1].lerp = 0;
4286 rsurface.frameblend[2].frame = 0;
4287 rsurface.frameblend[2].lerp = 0;
4288 rsurface.frameblend[3].frame = 0;
4289 rsurface.frameblend[3].lerp = 0;
4290 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4291 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4292 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4293 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4294 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4295 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4296 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4297 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4298 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4299 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4300 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4301 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4302 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4303 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4304 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4305 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4306 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4307 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4308 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4309 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4310 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4311 rsurface.modelelement3i = model->surfmesh.data_element3i;
4312 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4313 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4314 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4315 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4316 rsurface.modelsurfaces = model->data_surfaces;
4317 rsurface.generatedvertex = false;
4318 rsurface.vertex3f = rsurface.modelvertex3f;
4319 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4320 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4321 rsurface.svector3f = rsurface.modelsvector3f;
4322 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4323 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4324 rsurface.tvector3f = rsurface.modeltvector3f;
4325 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4326 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4327 rsurface.normal3f = rsurface.modelnormal3f;
4328 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4329 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4330 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4333 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4335 model_t *model = ent->model;
4337 if (rsurface.array_size < model->surfmesh.num_vertices)
4338 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4339 rsurface.matrix = ent->matrix;
4340 rsurface.inversematrix = ent->inversematrix;
4341 R_Mesh_Matrix(&rsurface.matrix);
4342 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4343 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4344 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4345 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4346 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4347 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4348 rsurface.frameblend[0] = ent->frameblend[0];
4349 rsurface.frameblend[1] = ent->frameblend[1];
4350 rsurface.frameblend[2] = ent->frameblend[2];
4351 rsurface.frameblend[3] = ent->frameblend[3];
4352 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4356 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4357 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4358 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4359 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4360 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4362 else if (wantnormals)
4364 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4365 rsurface.modelsvector3f = NULL;
4366 rsurface.modeltvector3f = NULL;
4367 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4368 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4372 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4373 rsurface.modelsvector3f = NULL;
4374 rsurface.modeltvector3f = NULL;
4375 rsurface.modelnormal3f = NULL;
4376 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4378 rsurface.modelvertex3f_bufferobject = 0;
4379 rsurface.modelvertex3f_bufferoffset = 0;
4380 rsurface.modelsvector3f_bufferobject = 0;
4381 rsurface.modelsvector3f_bufferoffset = 0;
4382 rsurface.modeltvector3f_bufferobject = 0;
4383 rsurface.modeltvector3f_bufferoffset = 0;
4384 rsurface.modelnormal3f_bufferobject = 0;
4385 rsurface.modelnormal3f_bufferoffset = 0;
4386 rsurface.generatedvertex = true;
4390 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4391 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4392 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4393 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4394 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4395 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4396 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4397 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4398 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4399 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4400 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4401 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4402 rsurface.generatedvertex = false;
4404 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4405 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4406 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4407 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4408 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4409 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4410 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4411 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4412 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4413 rsurface.modelelement3i = model->surfmesh.data_element3i;
4414 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4415 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4416 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4417 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4418 rsurface.modelsurfaces = model->data_surfaces;
4419 rsurface.vertex3f = rsurface.modelvertex3f;
4420 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4421 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4422 rsurface.svector3f = rsurface.modelsvector3f;
4423 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4424 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4425 rsurface.tvector3f = rsurface.modeltvector3f;
4426 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4427 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4428 rsurface.normal3f = rsurface.modelnormal3f;
4429 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4430 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4431 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4434 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4435 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4438 int texturesurfaceindex;
4443 const float *v1, *in_tc;
4445 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4447 q3shaderinfo_deform_t *deform;
4448 // 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
4449 if (rsurface.generatedvertex)
4451 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4452 generatenormals = true;
4453 for (i = 0;i < Q3MAXDEFORMS;i++)
4455 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4457 generatetangents = true;
4458 generatenormals = true;
4460 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4461 generatenormals = true;
4463 if (generatenormals && !rsurface.modelnormal3f)
4465 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4466 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4467 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4468 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4470 if (generatetangents && !rsurface.modelsvector3f)
4472 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4473 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4474 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4475 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4476 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4477 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4478 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);
4481 rsurface.vertex3f = rsurface.modelvertex3f;
4482 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4483 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4484 rsurface.svector3f = rsurface.modelsvector3f;
4485 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4486 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4487 rsurface.tvector3f = rsurface.modeltvector3f;
4488 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4489 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4490 rsurface.normal3f = rsurface.modelnormal3f;
4491 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4492 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4493 // if vertices are deformed (sprite flares and things in maps, possibly
4494 // water waves, bulges and other deformations), generate them into
4495 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4496 // (may be static model data or generated data for an animated model, or
4497 // the previous deform pass)
4498 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4500 switch (deform->deform)
4503 case Q3DEFORM_PROJECTIONSHADOW:
4504 case Q3DEFORM_TEXT0:
4505 case Q3DEFORM_TEXT1:
4506 case Q3DEFORM_TEXT2:
4507 case Q3DEFORM_TEXT3:
4508 case Q3DEFORM_TEXT4:
4509 case Q3DEFORM_TEXT5:
4510 case Q3DEFORM_TEXT6:
4511 case Q3DEFORM_TEXT7:
4514 case Q3DEFORM_AUTOSPRITE:
4515 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4516 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4517 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4518 VectorNormalize(newforward);
4519 VectorNormalize(newright);
4520 VectorNormalize(newup);
4521 // make deformed versions of only the model vertices used by the specified surfaces
4522 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4524 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4525 // a single autosprite surface can contain multiple sprites...
4526 for (j = 0;j < surface->num_vertices - 3;j += 4)
4528 VectorClear(center);
4529 for (i = 0;i < 4;i++)
4530 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4531 VectorScale(center, 0.25f, center);
4532 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4533 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4534 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4535 for (i = 0;i < 4;i++)
4537 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4538 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4541 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);
4542 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);
4544 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4545 rsurface.vertex3f_bufferobject = 0;
4546 rsurface.vertex3f_bufferoffset = 0;
4547 rsurface.svector3f = rsurface.array_deformedsvector3f;
4548 rsurface.svector3f_bufferobject = 0;
4549 rsurface.svector3f_bufferoffset = 0;
4550 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4551 rsurface.tvector3f_bufferobject = 0;
4552 rsurface.tvector3f_bufferoffset = 0;
4553 rsurface.normal3f = rsurface.array_deformednormal3f;
4554 rsurface.normal3f_bufferobject = 0;
4555 rsurface.normal3f_bufferoffset = 0;
4557 case Q3DEFORM_AUTOSPRITE2:
4558 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4559 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4560 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4561 VectorNormalize(newforward);
4562 VectorNormalize(newright);
4563 VectorNormalize(newup);
4564 // make deformed versions of only the model vertices used by the specified surfaces
4565 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4567 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4568 const float *v1, *v2;
4578 memset(shortest, 0, sizeof(shortest));
4579 // a single autosprite surface can contain multiple sprites...
4580 for (j = 0;j < surface->num_vertices - 3;j += 4)
4582 VectorClear(center);
4583 for (i = 0;i < 4;i++)
4584 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4585 VectorScale(center, 0.25f, center);
4586 // find the two shortest edges, then use them to define the
4587 // axis vectors for rotating around the central axis
4588 for (i = 0;i < 6;i++)
4590 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4591 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4593 Debug_PolygonBegin(NULL, 0, false, 0);
4594 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4595 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);
4596 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4599 l = VectorDistance2(v1, v2);
4600 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4602 l += (1.0f / 1024.0f);
4603 if (shortest[0].length2 > l || i == 0)
4605 shortest[1] = shortest[0];
4606 shortest[0].length2 = l;
4607 shortest[0].v1 = v1;
4608 shortest[0].v2 = v2;
4610 else if (shortest[1].length2 > l || i == 1)
4612 shortest[1].length2 = l;
4613 shortest[1].v1 = v1;
4614 shortest[1].v2 = v2;
4617 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4618 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4620 Debug_PolygonBegin(NULL, 0, false, 0);
4621 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4622 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);
4623 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4626 // this calculates the right vector from the shortest edge
4627 // and the up vector from the edge midpoints
4628 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4629 VectorNormalize(right);
4630 VectorSubtract(end, start, up);
4631 VectorNormalize(up);
4632 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4633 //VectorSubtract(rsurface.modelorg, center, forward);
4634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4635 VectorNegate(forward, forward);
4636 VectorReflect(forward, 0, up, forward);
4637 VectorNormalize(forward);
4638 CrossProduct(up, forward, newright);
4639 VectorNormalize(newright);
4641 Debug_PolygonBegin(NULL, 0, false, 0);
4642 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);
4643 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4644 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4648 Debug_PolygonBegin(NULL, 0, false, 0);
4649 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4650 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4651 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4654 // rotate the quad around the up axis vector, this is made
4655 // especially easy by the fact we know the quad is flat,
4656 // so we only have to subtract the center position and
4657 // measure distance along the right vector, and then
4658 // multiply that by the newright vector and add back the
4660 // we also need to subtract the old position to undo the
4661 // displacement from the center, which we do with a
4662 // DotProduct, the subtraction/addition of center is also
4663 // optimized into DotProducts here
4664 l = DotProduct(right, center);
4665 for (i = 0;i < 4;i++)
4667 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4668 f = DotProduct(right, v1) - l;
4669 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4672 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);
4673 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);
4675 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4676 rsurface.vertex3f_bufferobject = 0;
4677 rsurface.vertex3f_bufferoffset = 0;
4678 rsurface.svector3f = rsurface.array_deformedsvector3f;
4679 rsurface.svector3f_bufferobject = 0;
4680 rsurface.svector3f_bufferoffset = 0;
4681 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4682 rsurface.tvector3f_bufferobject = 0;
4683 rsurface.tvector3f_bufferoffset = 0;
4684 rsurface.normal3f = rsurface.array_deformednormal3f;
4685 rsurface.normal3f_bufferobject = 0;
4686 rsurface.normal3f_bufferoffset = 0;
4688 case Q3DEFORM_NORMAL:
4689 // deform the normals to make reflections wavey
4690 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4692 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4693 for (j = 0;j < surface->num_vertices;j++)
4696 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4697 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4698 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4699 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4700 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4701 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4702 VectorNormalize(normal);
4704 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);
4706 rsurface.svector3f = rsurface.array_deformedsvector3f;
4707 rsurface.svector3f_bufferobject = 0;
4708 rsurface.svector3f_bufferoffset = 0;
4709 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4710 rsurface.tvector3f_bufferobject = 0;
4711 rsurface.tvector3f_bufferoffset = 0;
4712 rsurface.normal3f = rsurface.array_deformednormal3f;
4713 rsurface.normal3f_bufferobject = 0;
4714 rsurface.normal3f_bufferoffset = 0;
4717 // deform vertex array to make wavey water and flags and such
4718 waveparms[0] = deform->waveparms[0];
4719 waveparms[1] = deform->waveparms[1];
4720 waveparms[2] = deform->waveparms[2];
4721 waveparms[3] = deform->waveparms[3];
4722 // this is how a divisor of vertex influence on deformation
4723 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4724 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4725 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4727 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4728 for (j = 0;j < surface->num_vertices;j++)
4730 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4731 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4732 // if the wavefunc depends on time, evaluate it per-vertex
4735 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4736 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4738 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4741 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4742 rsurface.vertex3f_bufferobject = 0;
4743 rsurface.vertex3f_bufferoffset = 0;
4745 case Q3DEFORM_BULGE:
4746 // deform vertex array to make the surface have moving bulges
4747 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4749 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4750 for (j = 0;j < surface->num_vertices;j++)
4752 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4753 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4756 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4757 rsurface.vertex3f_bufferobject = 0;
4758 rsurface.vertex3f_bufferoffset = 0;
4761 // deform vertex array
4762 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4763 VectorScale(deform->parms, scale, waveparms);
4764 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4766 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4767 for (j = 0;j < surface->num_vertices;j++)
4768 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4770 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4771 rsurface.vertex3f_bufferobject = 0;
4772 rsurface.vertex3f_bufferoffset = 0;
4776 // generate texcoords based on the chosen texcoord source
4777 switch(rsurface.texture->tcgen.tcgen)
4780 case Q3TCGEN_TEXTURE:
4781 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4782 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4783 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4785 case Q3TCGEN_LIGHTMAP:
4786 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4787 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4788 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4790 case Q3TCGEN_VECTOR:
4791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4793 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4794 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)
4796 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4797 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4800 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4801 rsurface.texcoordtexture2f_bufferobject = 0;
4802 rsurface.texcoordtexture2f_bufferoffset = 0;
4804 case Q3TCGEN_ENVIRONMENT:
4805 // make environment reflections using a spheremap
4806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4808 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4809 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4810 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4811 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4812 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4814 float l, d, eyedir[3];
4815 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4816 l = 0.5f / VectorLength(eyedir);
4817 d = DotProduct(normal, eyedir)*2;
4818 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4819 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4822 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4823 rsurface.texcoordtexture2f_bufferobject = 0;
4824 rsurface.texcoordtexture2f_bufferoffset = 0;
4827 // the only tcmod that needs software vertex processing is turbulent, so
4828 // check for it here and apply the changes if needed
4829 // and we only support that as the first one
4830 // (handling a mixture of turbulent and other tcmods would be problematic
4831 // without punting it entirely to a software path)
4832 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4834 amplitude = rsurface.texture->tcmods[0].parms[1];
4835 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4838 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4839 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)
4841 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4842 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4845 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4846 rsurface.texcoordtexture2f_bufferobject = 0;
4847 rsurface.texcoordtexture2f_bufferoffset = 0;
4849 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4850 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4851 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4852 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4855 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4858 const msurface_t *surface = texturesurfacelist[0];
4859 const msurface_t *surface2;
4864 // TODO: lock all array ranges before render, rather than on each surface
4865 if (texturenumsurfaces == 1)
4867 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4868 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));
4870 else if (r_batchmode.integer == 2)
4872 #define MAXBATCHTRIANGLES 4096
4873 int batchtriangles = 0;
4874 int batchelements[MAXBATCHTRIANGLES*3];
4875 for (i = 0;i < texturenumsurfaces;i = j)
4877 surface = texturesurfacelist[i];
4879 if (surface->num_triangles > MAXBATCHTRIANGLES)
4881 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));
4884 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4885 batchtriangles = surface->num_triangles;
4886 firstvertex = surface->num_firstvertex;
4887 endvertex = surface->num_firstvertex + surface->num_vertices;
4888 for (;j < texturenumsurfaces;j++)
4890 surface2 = texturesurfacelist[j];
4891 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4893 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4894 batchtriangles += surface2->num_triangles;
4895 firstvertex = min(firstvertex, surface2->num_firstvertex);
4896 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4898 surface2 = texturesurfacelist[j-1];
4899 numvertices = endvertex - firstvertex;
4900 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4903 else if (r_batchmode.integer == 1)
4905 for (i = 0;i < texturenumsurfaces;i = j)
4907 surface = texturesurfacelist[i];
4908 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4909 if (texturesurfacelist[j] != surface2)
4911 surface2 = texturesurfacelist[j-1];
4912 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4913 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4914 GL_LockArrays(surface->num_firstvertex, numvertices);
4915 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4920 for (i = 0;i < texturenumsurfaces;i++)
4922 surface = texturesurfacelist[i];
4923 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4924 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));
4929 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4931 int i, planeindex, vertexindex;
4935 r_waterstate_waterplane_t *p, *bestp;
4936 msurface_t *surface;
4937 if (r_waterstate.renderingscene)
4939 for (i = 0;i < texturenumsurfaces;i++)
4941 surface = texturesurfacelist[i];
4942 if (lightmaptexunit >= 0)
4943 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4944 if (deluxemaptexunit >= 0)
4945 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4946 // pick the closest matching water plane
4949 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4952 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4954 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4955 d += fabs(PlaneDiff(vert, &p->plane));
4957 if (bestd > d || !bestp)
4965 if (refractiontexunit >= 0)
4966 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4967 if (reflectiontexunit >= 0)
4968 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4972 if (refractiontexunit >= 0)
4973 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4974 if (reflectiontexunit >= 0)
4975 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4977 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4978 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4982 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4986 const msurface_t *surface = texturesurfacelist[0];
4987 const msurface_t *surface2;
4992 // TODO: lock all array ranges before render, rather than on each surface
4993 if (texturenumsurfaces == 1)
4995 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4996 if (deluxemaptexunit >= 0)
4997 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4998 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4999 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));
5001 else if (r_batchmode.integer == 2)
5003 #define MAXBATCHTRIANGLES 4096
5004 int batchtriangles = 0;
5005 int batchelements[MAXBATCHTRIANGLES*3];
5006 for (i = 0;i < texturenumsurfaces;i = j)
5008 surface = texturesurfacelist[i];
5009 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5010 if (deluxemaptexunit >= 0)
5011 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5013 if (surface->num_triangles > MAXBATCHTRIANGLES)
5015 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));
5018 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5019 batchtriangles = surface->num_triangles;
5020 firstvertex = surface->num_firstvertex;
5021 endvertex = surface->num_firstvertex + surface->num_vertices;
5022 for (;j < texturenumsurfaces;j++)
5024 surface2 = texturesurfacelist[j];
5025 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5027 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5028 batchtriangles += surface2->num_triangles;
5029 firstvertex = min(firstvertex, surface2->num_firstvertex);
5030 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5032 surface2 = texturesurfacelist[j-1];
5033 numvertices = endvertex - firstvertex;
5034 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5037 else if (r_batchmode.integer == 1)
5040 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5041 for (i = 0;i < texturenumsurfaces;i = j)
5043 surface = texturesurfacelist[i];
5044 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5045 if (texturesurfacelist[j] != surface2)
5047 Con_Printf(" %i", j - i);
5050 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5052 for (i = 0;i < texturenumsurfaces;i = j)
5054 surface = texturesurfacelist[i];
5055 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5056 if (deluxemaptexunit >= 0)
5057 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5058 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5059 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5062 Con_Printf(" %i", j - i);
5064 surface2 = texturesurfacelist[j-1];
5065 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5066 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5067 GL_LockArrays(surface->num_firstvertex, numvertices);
5068 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5076 for (i = 0;i < texturenumsurfaces;i++)
5078 surface = texturesurfacelist[i];
5079 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5080 if (deluxemaptexunit >= 0)
5081 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5082 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5083 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));
5088 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5091 int texturesurfaceindex;
5092 if (r_showsurfaces.integer == 2)
5094 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5096 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5097 for (j = 0;j < surface->num_triangles;j++)
5099 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5100 GL_Color(f, f, f, 1);
5101 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)));
5107 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5109 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5110 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5111 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);
5112 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5113 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));
5118 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5120 int texturesurfaceindex;
5124 if (rsurface.lightmapcolor4f)
5126 // generate color arrays for the surfaces in this list
5127 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5129 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5130 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)
5132 f = FogPoint_Model(v);
5142 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5144 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5145 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)
5147 f = FogPoint_Model(v);
5155 rsurface.lightmapcolor4f = rsurface.array_color4f;
5156 rsurface.lightmapcolor4f_bufferobject = 0;
5157 rsurface.lightmapcolor4f_bufferoffset = 0;
5160 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5162 int texturesurfaceindex;
5165 if (!rsurface.lightmapcolor4f)
5167 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5169 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5170 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)
5178 rsurface.lightmapcolor4f = rsurface.array_color4f;
5179 rsurface.lightmapcolor4f_bufferobject = 0;
5180 rsurface.lightmapcolor4f_bufferoffset = 0;
5183 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5186 rsurface.lightmapcolor4f = NULL;
5187 rsurface.lightmapcolor4f_bufferobject = 0;
5188 rsurface.lightmapcolor4f_bufferoffset = 0;
5189 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5190 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5191 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5192 GL_Color(r, g, b, a);
5193 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5196 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5198 // TODO: optimize applyfog && applycolor case
5199 // just apply fog if necessary, and tint the fog color array if necessary
5200 rsurface.lightmapcolor4f = NULL;
5201 rsurface.lightmapcolor4f_bufferobject = 0;
5202 rsurface.lightmapcolor4f_bufferoffset = 0;
5203 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5204 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5205 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5206 GL_Color(r, g, b, a);
5207 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5210 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5212 int texturesurfaceindex;
5216 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5218 // generate color arrays for the surfaces in this list
5219 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5221 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5222 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5224 if (surface->lightmapinfo->samples)
5226 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5227 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5228 VectorScale(lm, scale, c);
5229 if (surface->lightmapinfo->styles[1] != 255)
5231 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5233 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5234 VectorMA(c, scale, lm, c);
5235 if (surface->lightmapinfo->styles[2] != 255)
5238 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5239 VectorMA(c, scale, lm, c);
5240 if (surface->lightmapinfo->styles[3] != 255)
5243 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5244 VectorMA(c, scale, lm, c);
5254 rsurface.lightmapcolor4f = rsurface.array_color4f;
5255 rsurface.lightmapcolor4f_bufferobject = 0;
5256 rsurface.lightmapcolor4f_bufferoffset = 0;
5260 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5261 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5262 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5264 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5265 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5266 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5267 GL_Color(r, g, b, a);
5268 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5271 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5273 int texturesurfaceindex;
5277 vec3_t ambientcolor;
5278 vec3_t diffusecolor;
5282 VectorCopy(rsurface.modellight_lightdir, lightdir);
5283 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5284 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5285 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5286 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5287 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5288 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5289 if (VectorLength2(diffusecolor) > 0)
5291 // generate color arrays for the surfaces in this list
5292 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5294 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5295 int numverts = surface->num_vertices;
5296 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5297 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5298 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5299 // q3-style directional shading
5300 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5302 if ((f = DotProduct(c2, lightdir)) > 0)
5303 VectorMA(ambientcolor, f, diffusecolor, c);
5305 VectorCopy(ambientcolor, c);
5314 rsurface.lightmapcolor4f = rsurface.array_color4f;
5315 rsurface.lightmapcolor4f_bufferobject = 0;
5316 rsurface.lightmapcolor4f_bufferoffset = 0;
5320 r = ambientcolor[0];
5321 g = ambientcolor[1];
5322 b = ambientcolor[2];
5323 rsurface.lightmapcolor4f = NULL;
5324 rsurface.lightmapcolor4f_bufferobject = 0;
5325 rsurface.lightmapcolor4f_bufferoffset = 0;
5327 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5328 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5329 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5330 GL_Color(r, g, b, a);
5331 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5334 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5336 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5337 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5338 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5339 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5340 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5342 rsurface.mode = RSURFMODE_SHOWSURFACES;
5344 GL_BlendFunc(GL_ONE, GL_ZERO);
5345 R_Mesh_ColorPointer(NULL, 0, 0);
5346 R_Mesh_ResetTextureState();
5348 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5349 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5352 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5354 // transparent sky would be ridiculous
5355 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5357 if (rsurface.mode != RSURFMODE_SKY)
5359 if (rsurface.mode == RSURFMODE_GLSL)
5361 qglUseProgramObjectARB(0);CHECKGLERROR
5363 rsurface.mode = RSURFMODE_SKY;
5367 skyrendernow = false;
5369 // restore entity matrix
5370 R_Mesh_Matrix(&rsurface.matrix);
5372 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5373 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5374 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5375 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5377 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5378 // skymasking on them, and Quake3 never did sky masking (unlike
5379 // software Quake and software Quake2), so disable the sky masking
5380 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5381 // and skymasking also looks very bad when noclipping outside the
5382 // level, so don't use it then either.
5383 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5385 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5386 R_Mesh_ColorPointer(NULL, 0, 0);
5387 R_Mesh_ResetTextureState();
5388 if (skyrendermasked)
5390 // depth-only (masking)
5391 GL_ColorMask(0,0,0,0);
5392 // just to make sure that braindead drivers don't draw
5393 // anything despite that colormask...
5394 GL_BlendFunc(GL_ZERO, GL_ONE);
5399 GL_BlendFunc(GL_ONE, GL_ZERO);
5401 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5402 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5403 if (skyrendermasked)
5404 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5408 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5410 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5413 if (rsurface.mode != RSURFMODE_GLSL)
5415 rsurface.mode = RSURFMODE_GLSL;
5416 R_Mesh_ResetTextureState();
5419 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5420 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5421 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5422 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5423 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5424 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5425 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5426 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5428 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5429 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5430 R_Mesh_ColorPointer(NULL, 0, 0);
5432 else if (rsurface.uselightmaptexture)
5434 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5435 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5436 R_Mesh_ColorPointer(NULL, 0, 0);
5440 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5441 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5442 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5444 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5445 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5446 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5448 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5450 // render background
5451 GL_BlendFunc(GL_ONE, GL_ZERO);
5453 GL_AlphaTest(false);
5455 GL_Color(1, 1, 1, 1);
5456 R_Mesh_ColorPointer(NULL, 0, 0);
5458 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5459 if (r_glsl_permutation)
5461 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5462 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5463 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5464 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5465 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5466 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5467 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5470 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5471 GL_DepthMask(false);
5472 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5473 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5475 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5476 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5477 R_Mesh_ColorPointer(NULL, 0, 0);
5479 else if (rsurface.uselightmaptexture)
5481 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5482 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5483 R_Mesh_ColorPointer(NULL, 0, 0);
5487 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5488 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5489 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5491 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5492 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5495 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5496 if (!r_glsl_permutation)
5499 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5500 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5501 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5502 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5503 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5504 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5505 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]);
5507 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5509 GL_BlendFunc(GL_ONE, GL_ZERO);
5511 GL_AlphaTest(false);
5514 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5516 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5517 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);
5519 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5523 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5524 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);
5526 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5528 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5533 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5535 // OpenGL 1.3 path - anything not completely ancient
5536 int texturesurfaceindex;
5537 qboolean applycolor;
5541 const texturelayer_t *layer;
5542 if (rsurface.mode != RSURFMODE_MULTIPASS)
5543 rsurface.mode = RSURFMODE_MULTIPASS;
5544 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5546 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5549 int layertexrgbscale;
5550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5552 if (layerindex == 0)
5556 GL_AlphaTest(false);
5557 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5560 GL_DepthMask(layer->depthmask);
5561 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5562 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5564 layertexrgbscale = 4;
5565 VectorScale(layer->color, 0.25f, layercolor);
5567 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5569 layertexrgbscale = 2;
5570 VectorScale(layer->color, 0.5f, layercolor);
5574 layertexrgbscale = 1;
5575 VectorScale(layer->color, 1.0f, layercolor);
5577 layercolor[3] = layer->color[3];
5578 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5579 R_Mesh_ColorPointer(NULL, 0, 0);
5580 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5581 switch (layer->type)
5583 case TEXTURELAYERTYPE_LITTEXTURE:
5584 memset(&m, 0, sizeof(m));
5585 m.tex[0] = R_GetTexture(r_texture_white);
5586 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5587 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5588 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5589 m.tex[1] = R_GetTexture(layer->texture);
5590 m.texmatrix[1] = layer->texmatrix;
5591 m.texrgbscale[1] = layertexrgbscale;
5592 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5593 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5594 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5595 R_Mesh_TextureState(&m);
5596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5597 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5598 else if (rsurface.uselightmaptexture)
5599 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5601 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5603 case TEXTURELAYERTYPE_TEXTURE:
5604 memset(&m, 0, sizeof(m));
5605 m.tex[0] = R_GetTexture(layer->texture);
5606 m.texmatrix[0] = layer->texmatrix;
5607 m.texrgbscale[0] = layertexrgbscale;
5608 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5609 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5610 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5611 R_Mesh_TextureState(&m);
5612 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5614 case TEXTURELAYERTYPE_FOG:
5615 memset(&m, 0, sizeof(m));
5616 m.texrgbscale[0] = layertexrgbscale;
5619 m.tex[0] = R_GetTexture(layer->texture);
5620 m.texmatrix[0] = layer->texmatrix;
5621 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5622 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5623 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5625 R_Mesh_TextureState(&m);
5626 // generate a color array for the fog pass
5627 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5632 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5633 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)
5635 f = 1 - FogPoint_Model(v);
5636 c[0] = layercolor[0];
5637 c[1] = layercolor[1];
5638 c[2] = layercolor[2];
5639 c[3] = f * layercolor[3];
5642 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5645 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5647 GL_LockArrays(0, 0);
5650 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5652 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5653 GL_AlphaTest(false);
5657 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5659 // OpenGL 1.1 - crusty old voodoo path
5660 int texturesurfaceindex;
5664 const texturelayer_t *layer;
5665 if (rsurface.mode != RSURFMODE_MULTIPASS)
5666 rsurface.mode = RSURFMODE_MULTIPASS;
5667 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5669 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5673 if (layerindex == 0)
5677 GL_AlphaTest(false);
5678 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5681 GL_DepthMask(layer->depthmask);
5682 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5683 R_Mesh_ColorPointer(NULL, 0, 0);
5684 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5685 switch (layer->type)
5687 case TEXTURELAYERTYPE_LITTEXTURE:
5688 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5690 // two-pass lit texture with 2x rgbscale
5691 // first the lightmap pass
5692 memset(&m, 0, sizeof(m));
5693 m.tex[0] = R_GetTexture(r_texture_white);
5694 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5695 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5696 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5697 R_Mesh_TextureState(&m);
5698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5699 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5700 else if (rsurface.uselightmaptexture)
5701 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5703 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5704 GL_LockArrays(0, 0);
5705 // then apply the texture to it
5706 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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);
5714 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);
5718 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5719 memset(&m, 0, sizeof(m));
5720 m.tex[0] = R_GetTexture(layer->texture);
5721 m.texmatrix[0] = layer->texmatrix;
5722 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5723 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5724 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5725 R_Mesh_TextureState(&m);
5726 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5727 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);
5729 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);
5732 case TEXTURELAYERTYPE_TEXTURE:
5733 // singletexture unlit texture with transparency support
5734 memset(&m, 0, sizeof(m));
5735 m.tex[0] = R_GetTexture(layer->texture);
5736 m.texmatrix[0] = layer->texmatrix;
5737 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5738 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5739 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5740 R_Mesh_TextureState(&m);
5741 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);
5743 case TEXTURELAYERTYPE_FOG:
5744 // singletexture fogging
5745 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5748 memset(&m, 0, sizeof(m));
5749 m.tex[0] = R_GetTexture(layer->texture);
5750 m.texmatrix[0] = layer->texmatrix;
5751 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5752 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5753 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5754 R_Mesh_TextureState(&m);
5757 R_Mesh_ResetTextureState();
5758 // generate a color array for the fog pass
5759 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5763 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5764 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)
5766 f = 1 - FogPoint_Model(v);
5767 c[0] = layer->color[0];
5768 c[1] = layer->color[1];
5769 c[2] = layer->color[2];
5770 c[3] = f * layer->color[3];
5773 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5776 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5778 GL_LockArrays(0, 0);
5781 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5783 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5784 GL_AlphaTest(false);
5788 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5790 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5792 rsurface.rtlight = NULL;
5796 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5798 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5800 if (rsurface.mode != RSURFMODE_MULTIPASS)
5801 rsurface.mode = RSURFMODE_MULTIPASS;
5802 if (r_depthfirst.integer == 3)
5804 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5805 if (!r_view.showdebug)
5806 GL_Color(0, 0, 0, 1);
5808 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5812 GL_ColorMask(0,0,0,0);
5815 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5816 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5817 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5819 GL_BlendFunc(GL_ONE, GL_ZERO);
5821 GL_AlphaTest(false);
5822 R_Mesh_ColorPointer(NULL, 0, 0);
5823 R_Mesh_ResetTextureState();
5824 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5825 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5826 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5828 else if (r_depthfirst.integer == 3)
5830 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5832 GL_Color(0, 0, 0, 1);
5833 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5835 else if (r_showsurfaces.integer)
5837 if (rsurface.mode != RSURFMODE_MULTIPASS)
5838 rsurface.mode = RSURFMODE_MULTIPASS;
5839 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5840 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5842 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5843 GL_BlendFunc(GL_ONE, GL_ZERO);
5844 GL_DepthMask(writedepth);
5846 GL_AlphaTest(false);
5847 R_Mesh_ColorPointer(NULL, 0, 0);
5848 R_Mesh_ResetTextureState();
5849 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5850 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5852 else if (gl_lightmaps.integer)
5855 if (rsurface.mode != RSURFMODE_MULTIPASS)
5856 rsurface.mode = RSURFMODE_MULTIPASS;
5857 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5859 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5860 GL_BlendFunc(GL_ONE, GL_ZERO);
5861 GL_DepthMask(writedepth);
5863 GL_AlphaTest(false);
5864 R_Mesh_ColorPointer(NULL, 0, 0);
5865 memset(&m, 0, sizeof(m));
5866 m.tex[0] = R_GetTexture(r_texture_white);
5867 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5868 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5869 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5870 R_Mesh_TextureState(&m);
5871 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5872 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5873 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5874 else if (rsurface.uselightmaptexture)
5875 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5877 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5879 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5880 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5881 else if (rsurface.texture->currentnumlayers)
5883 // write depth for anything we skipped on the depth-only pass earlier
5884 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5886 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5887 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5888 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5889 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5890 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5891 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5892 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5893 if (r_glsl.integer && gl_support_fragment_shader)
5894 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5895 else if (gl_combine.integer && r_textureunits.integer >= 2)
5896 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5898 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5901 GL_LockArrays(0, 0);
5904 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5907 int texturenumsurfaces, endsurface;
5909 msurface_t *surface;
5910 msurface_t *texturesurfacelist[1024];
5912 // if the model is static it doesn't matter what value we give for
5913 // wantnormals and wanttangents, so this logic uses only rules applicable
5914 // to a model, knowing that they are meaningless otherwise
5915 if (ent == r_refdef.worldentity)
5916 RSurf_ActiveWorldEntity();
5917 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5918 RSurf_ActiveModelEntity(ent, false, false);
5920 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5922 for (i = 0;i < numsurfaces;i = j)
5925 surface = rsurface.modelsurfaces + surfacelist[i];
5926 texture = surface->texture;
5927 R_UpdateTextureInfo(ent, texture);
5928 rsurface.texture = texture->currentframe;
5929 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5930 // scan ahead until we find a different texture
5931 endsurface = min(i + 1024, numsurfaces);
5932 texturenumsurfaces = 0;
5933 texturesurfacelist[texturenumsurfaces++] = surface;
5934 for (;j < endsurface;j++)
5936 surface = rsurface.modelsurfaces + surfacelist[j];
5937 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5939 texturesurfacelist[texturenumsurfaces++] = surface;
5941 // render the range of surfaces
5942 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5948 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5951 vec3_t tempcenter, center;
5953 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5956 for (i = 0;i < numsurfaces;i++)
5957 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5958 R_Water_AddWaterPlane(surfacelist[i]);
5961 // break the surface list down into batches by texture and use of lightmapping
5962 for (i = 0;i < numsurfaces;i = j)
5965 // texture is the base texture pointer, rsurface.texture is the
5966 // current frame/skin the texture is directing us to use (for example
5967 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5968 // use skin 1 instead)
5969 texture = surfacelist[i]->texture;
5970 rsurface.texture = texture->currentframe;
5971 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5972 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5974 // if this texture is not the kind we want, skip ahead to the next one
5975 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5979 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5981 // transparent surfaces get pushed off into the transparent queue
5982 const msurface_t *surface = surfacelist[i];
5985 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5986 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5987 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5988 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5989 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5993 // simply scan ahead until we find a different texture or lightmap state
5994 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5996 // render the range of surfaces
5997 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6002 float locboxvertex3f[6*4*3] =
6004 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6005 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6006 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6007 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6008 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6009 1,0,0, 0,0,0, 0,1,0, 1,1,0
6012 int locboxelement3i[6*2*3] =
6022 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6025 cl_locnode_t *loc = (cl_locnode_t *)ent;
6027 float vertex3f[6*4*3];
6029 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6030 GL_DepthMask(false);
6031 GL_DepthRange(0, 1);
6032 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6034 GL_CullFace(GL_NONE);
6035 R_Mesh_Matrix(&identitymatrix);
6037 R_Mesh_VertexPointer(vertex3f, 0, 0);
6038 R_Mesh_ColorPointer(NULL, 0, 0);
6039 R_Mesh_ResetTextureState();
6042 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6043 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6044 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6045 surfacelist[0] < 0 ? 0.5f : 0.125f);
6047 if (VectorCompare(loc->mins, loc->maxs))
6049 VectorSet(size, 2, 2, 2);
6050 VectorMA(loc->mins, -0.5f, size, mins);
6054 VectorCopy(loc->mins, mins);
6055 VectorSubtract(loc->maxs, loc->mins, size);
6058 for (i = 0;i < 6*4*3;)
6059 for (j = 0;j < 3;j++, i++)
6060 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6062 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6065 void R_DrawLocs(void)
6068 cl_locnode_t *loc, *nearestloc;
6070 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6071 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6073 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6074 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6078 void R_DrawDebugModel(entity_render_t *ent)
6080 int i, j, k, l, flagsmask;
6081 const int *elements;
6083 msurface_t *surface;
6084 model_t *model = ent->model;
6087 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6089 R_Mesh_ColorPointer(NULL, 0, 0);
6090 R_Mesh_ResetTextureState();
6091 GL_DepthRange(0, 1);
6092 GL_DepthTest(!r_showdisabledepthtest.integer);
6093 GL_DepthMask(false);
6094 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6096 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6098 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6099 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6101 if (brush->colbrushf && brush->colbrushf->numtriangles)
6103 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6104 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);
6105 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6108 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6110 if (surface->num_collisiontriangles)
6112 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6113 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);
6114 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6119 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6121 if (r_showtris.integer || r_shownormals.integer)
6123 if (r_showdisabledepthtest.integer)
6125 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6126 GL_DepthMask(false);
6130 GL_BlendFunc(GL_ONE, GL_ZERO);
6133 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6135 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6137 rsurface.texture = surface->texture->currentframe;
6138 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6140 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6141 if (r_showtris.value > 0)
6143 if (!rsurface.texture->currentlayers->depthmask)
6144 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6145 else if (ent == r_refdef.worldentity)
6146 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6148 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6149 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6152 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6154 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6155 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6156 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6157 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6162 if (r_shownormals.value > 0)
6164 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6166 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6168 VectorCopy(rsurface.vertex3f + l * 3, v);
6169 qglVertex3f(v[0], v[1], v[2]);
6170 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6171 qglVertex3f(v[0], v[1], v[2]);
6175 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6177 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6179 VectorCopy(rsurface.vertex3f + l * 3, v);
6180 qglVertex3f(v[0], v[1], v[2]);
6181 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6182 qglVertex3f(v[0], v[1], v[2]);
6186 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6188 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6190 VectorCopy(rsurface.vertex3f + l * 3, v);
6191 qglVertex3f(v[0], v[1], v[2]);
6192 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6193 qglVertex3f(v[0], v[1], v[2]);
6200 rsurface.texture = NULL;
6204 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6205 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6207 int i, j, endj, f, flagsmask;
6208 msurface_t *surface, **surfacechain;
6210 model_t *model = r_refdef.worldmodel;
6211 const int maxsurfacelist = 1024;
6212 int numsurfacelist = 0;
6213 msurface_t *surfacelist[1024];
6217 RSurf_ActiveWorldEntity();
6219 // update light styles
6220 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6222 for (i = 0;i < model->brushq1.light_styles;i++)
6224 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6226 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6227 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6228 for (;(surface = *surfacechain);surfacechain++)
6229 surface->cached_dlight = true;
6234 R_UpdateAllTextureInfo(r_refdef.worldentity);
6235 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6239 R_DrawDebugModel(r_refdef.worldentity);
6245 rsurface.uselightmaptexture = false;
6246 rsurface.texture = NULL;
6248 j = model->firstmodelsurface;
6249 endj = j + model->nummodelsurfaces;
6252 // quickly skip over non-visible surfaces
6253 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6255 // quickly iterate over visible surfaces
6256 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6258 // process this surface
6259 surface = model->data_surfaces + j;
6260 // if this surface fits the criteria, add it to the list
6261 if (surface->num_triangles)
6263 // if lightmap parameters changed, rebuild lightmap texture
6264 if (surface->cached_dlight)
6265 R_BuildLightMap(r_refdef.worldentity, surface);
6266 // add face to draw list
6267 surfacelist[numsurfacelist++] = surface;
6268 r_refdef.stats.world_triangles += surface->num_triangles;
6269 if (numsurfacelist >= maxsurfacelist)
6271 r_refdef.stats.world_surfaces += numsurfacelist;
6272 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6278 r_refdef.stats.world_surfaces += numsurfacelist;
6280 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6284 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6286 int i, f, flagsmask;
6287 msurface_t *surface, *endsurface, **surfacechain;
6289 model_t *model = ent->model;
6290 const int maxsurfacelist = 1024;
6291 int numsurfacelist = 0;
6292 msurface_t *surfacelist[1024];
6296 // if the model is static it doesn't matter what value we give for
6297 // wantnormals and wanttangents, so this logic uses only rules applicable
6298 // to a model, knowing that they are meaningless otherwise
6299 if (ent == r_refdef.worldentity)
6300 RSurf_ActiveWorldEntity();
6301 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6302 RSurf_ActiveModelEntity(ent, false, false);
6304 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6306 // update light styles
6307 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6309 for (i = 0;i < model->brushq1.light_styles;i++)
6311 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6313 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6314 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6315 for (;(surface = *surfacechain);surfacechain++)
6316 surface->cached_dlight = true;
6321 R_UpdateAllTextureInfo(ent);
6322 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6326 R_DrawDebugModel(ent);
6332 rsurface.uselightmaptexture = false;
6333 rsurface.texture = NULL;
6335 surface = model->data_surfaces + model->firstmodelsurface;
6336 endsurface = surface + model->nummodelsurfaces;
6337 for (;surface < endsurface;surface++)
6339 // if this surface fits the criteria, add it to the list
6340 if (surface->num_triangles)
6342 // if lightmap parameters changed, rebuild lightmap texture
6343 if (surface->cached_dlight)
6344 R_BuildLightMap(ent, surface);
6345 // add face to draw list
6346 surfacelist[numsurfacelist++] = surface;
6347 r_refdef.stats.entities_triangles += surface->num_triangles;
6348 if (numsurfacelist >= maxsurfacelist)
6350 r_refdef.stats.entities_surfaces += numsurfacelist;
6351 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6356 r_refdef.stats.entities_surfaces += numsurfacelist;
6358 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);