2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
82 cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
83 cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
84 cvar_t r_glsl_water_refractcolor_r = {CVAR_SAVE, "r_glsl_water_refractcolor_r", "1", "water color tint for refraction"};
85 cvar_t r_glsl_water_refractcolor_g = {CVAR_SAVE, "r_glsl_water_refractcolor_g", "1", "water color tint for refraction"};
86 cvar_t r_glsl_water_refractcolor_b = {CVAR_SAVE, "r_glsl_water_refractcolor_b", "1", "water color tint for refraction"};
87 cvar_t r_glsl_water_reflectcolor_r = {CVAR_SAVE, "r_glsl_water_reflectcolor_r", "1", "water color tint for reflection"};
88 cvar_t r_glsl_water_reflectcolor_g = {CVAR_SAVE, "r_glsl_water_reflectcolor_g", "1", "water color tint for reflection"};
89 cvar_t r_glsl_water_reflectcolor_b = {CVAR_SAVE, "r_glsl_water_reflectcolor_b", "1", "water color tint for reflection"};
90 cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"};
92 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
93 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
95 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
96 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
112 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
114 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
121 extern qboolean v_flipped_state;
123 typedef struct r_glsl_bloomshader_s
126 int loc_Texture_Bloom;
128 r_glsl_bloomshader_t;
130 static struct r_bloomstate_s
135 int bloomwidth, bloomheight;
137 int screentexturewidth, screentextureheight;
138 rtexture_t *texture_screen;
140 int bloomtexturewidth, bloomtextureheight;
141 rtexture_t *texture_bloom;
143 r_glsl_bloomshader_t *shader;
145 // arrays for rendering the screen passes
146 float screentexcoord2f[8];
147 float bloomtexcoord2f[8];
148 float offsettexcoord2f[8];
152 typedef struct r_waterstate_waterplane_s
154 rtexture_t *texture_refraction;
155 rtexture_t *texture_reflection;
157 int materialflags; // combined flags of all water surfaces on this plane
159 r_waterstate_waterplane_t;
161 #define MAX_WATERPLANES 16
163 static struct r_waterstate_s
167 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
169 int waterwidth, waterheight;
170 int texturewidth, textureheight;
172 int maxwaterplanes; // same as MAX_WATERPLANES
174 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
176 float screenscale[2];
177 float screencenter[2];
181 // shadow volume bsp struct with automatically growing nodes buffer
184 rtexture_t *r_texture_blanknormalmap;
185 rtexture_t *r_texture_white;
186 rtexture_t *r_texture_grey128;
187 rtexture_t *r_texture_black;
188 rtexture_t *r_texture_notexture;
189 rtexture_t *r_texture_whitecube;
190 rtexture_t *r_texture_normalizationcube;
191 rtexture_t *r_texture_fogattenuation;
192 //rtexture_t *r_texture_fogintensity;
194 // information about each possible shader permutation
195 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
196 // currently selected permutation
197 r_glsl_permutation_t *r_glsl_permutation;
199 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
200 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
202 // vertex coordinates for a quad that covers the screen exactly
203 const static float r_screenvertex3f[12] =
211 extern void R_DrawModelShadows(void);
213 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
216 for (i = 0;i < verts;i++)
227 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
230 for (i = 0;i < verts;i++)
240 // FIXME: move this to client?
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_Set("gl_fogenable", "0");
246 Cvar_Set("gl_fogdensity", "0.2");
247 Cvar_Set("gl_fogred", "0.3");
248 Cvar_Set("gl_foggreen", "0.3");
249 Cvar_Set("gl_fogblue", "0.3");
251 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
254 float FogPoint_World(const vec3_t p)
256 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
260 float FogPoint_Model(const vec3_t p)
262 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
263 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
266 static void R_BuildBlankTextures(void)
268 unsigned char data[4];
269 data[0] = 128; // normal X
270 data[1] = 128; // normal Y
271 data[2] = 255; // normal Z
272 data[3] = 128; // height
273 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
278 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
288 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
291 static void R_BuildNoTexture(void)
294 unsigned char pix[16][16][4];
295 // this makes a light grey/dark grey checkerboard texture
296 for (y = 0;y < 16;y++)
298 for (x = 0;x < 16;x++)
300 if ((y < 8) ^ (x < 8))
316 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
319 static void R_BuildWhiteCube(void)
321 unsigned char data[6*1*1*4];
322 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
323 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
324 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
325 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
326 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
327 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 unsigned char data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380 intensity = 127.0f / sqrt(DotProduct(v, v));
381 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
382 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
383 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
384 data[side][y][x][3] = 255;
388 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
391 static void R_BuildFogTexture(void)
395 unsigned char data1[FOGWIDTH][4];
396 //unsigned char data2[FOGWIDTH][4];
397 for (x = 0;x < FOGWIDTH;x++)
399 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
404 //data2[x][0] = 255 - b;
405 //data2[x][1] = 255 - b;
406 //data2[x][2] = 255 - b;
409 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
410 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
413 static const char *builtinshaderstring =
414 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
415 "// written by Forest 'LordHavoc' Hale\n"
417 "// common definitions between vertex shader and fragment shader:\n"
419 "#ifdef __GLSL_CG_DATA_TYPES\n"
420 "# define myhalf half\n"
421 "# define myhvec2 hvec2\n"
422 "# define myhvec3 hvec3\n"
423 "# define myhvec4 hvec4\n"
425 "# define myhalf float\n"
426 "# define myhvec2 vec2\n"
427 "# define myhvec3 vec3\n"
428 "# define myhvec4 vec4\n"
431 "varying vec2 TexCoord;\n"
432 "varying vec2 TexCoordLightmap;\n"
434 "//#ifdef MODE_LIGHTSOURCE\n"
435 "varying vec3 CubeVector;\n"
438 "//#ifdef MODE_LIGHTSOURCE\n"
439 "varying vec3 LightVector;\n"
441 "//# ifdef MODE_LIGHTDIRECTION\n"
442 "//varying vec3 LightVector;\n"
446 "varying vec3 EyeVector;\n"
448 "varying vec3 EyeVectorModelSpace;\n"
451 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
452 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
453 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
455 "//#ifdef USEWATER\n"
456 "varying vec4 ModelViewProjectionPosition;\n"
458 "//# ifdef USEREFLECTION\n"
459 "//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(USEWATER) || 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"
533 " ModelViewProjectionPosition = gl_Position;\n"
535 "# ifdef USEREFLECTION\n"
536 " ModelViewProjectionPosition = gl_Position;\n"
541 "#endif // VERTEX_SHADER\n"
546 "// fragment shader specific:\n"
547 "#ifdef FRAGMENT_SHADER\n"
549 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
550 "uniform sampler2D Texture_Normal;\n"
551 "uniform sampler2D Texture_Color;\n"
552 "uniform sampler2D Texture_Gloss;\n"
553 "uniform samplerCube Texture_Cube;\n"
554 "uniform sampler2D Texture_Attenuation;\n"
555 "uniform sampler2D Texture_FogMask;\n"
556 "uniform sampler2D Texture_Pants;\n"
557 "uniform sampler2D Texture_Shirt;\n"
558 "uniform sampler2D Texture_Lightmap;\n"
559 "uniform sampler2D Texture_Deluxemap;\n"
560 "uniform sampler2D Texture_Glow;\n"
561 "uniform sampler2D Texture_Reflection;\n"
562 "uniform sampler2D Texture_Refraction;\n"
564 "uniform myhvec3 LightColor;\n"
565 "uniform myhvec3 AmbientColor;\n"
566 "uniform myhvec3 DiffuseColor;\n"
567 "uniform myhvec3 SpecularColor;\n"
568 "uniform myhvec3 Color_Pants;\n"
569 "uniform myhvec3 Color_Shirt;\n"
570 "uniform myhvec3 FogColor;\n"
572 "//#ifdef USEWATER\n"
573 "uniform vec4 DistortScaleRefractReflect;\n"
574 "uniform vec4 ScreenScaleRefractReflect;\n"
575 "uniform vec4 ScreenCenterRefractReflect;\n"
576 "uniform myhvec3 RefractColor;\n"
577 "uniform myhvec3 ReflectColor;\n"
579 "//# ifdef USEREFLECTION\n"
580 "//uniform vec4 DistortScaleRefractReflect;\n"
581 "//uniform vec4 ScreenScaleRefractReflect;\n"
582 "//uniform vec4 ScreenCenterRefractReflect;\n"
583 "//uniform myhvec3 ReflectColor;\n"
587 "uniform myhalf GlowScale;\n"
588 "uniform myhalf SceneBrightness;\n"
589 "#ifdef USECONTRASTBOOST\n"
590 "uniform myhalf ContrastBoostCoeff;\n"
593 "uniform float OffsetMapping_Scale;\n"
594 "uniform float OffsetMapping_Bias;\n"
595 "uniform float FogRangeRecip;\n"
597 "uniform myhalf AmbientScale;\n"
598 "uniform myhalf DiffuseScale;\n"
599 "uniform myhalf SpecularScale;\n"
600 "uniform myhalf SpecularPower;\n"
602 "#ifdef USEOFFSETMAPPING\n"
603 "vec2 OffsetMapping(vec2 TexCoord)\n"
605 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
606 " // 14 sample relief mapping: linear search and then binary search\n"
607 " // this basically steps forward a small amount repeatedly until it finds\n"
608 " // itself inside solid, then jitters forward and back using decreasing\n"
609 " // amounts to find the impact\n"
610 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
611 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
612 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
613 " vec3 RT = vec3(TexCoord, 1);\n"
614 " OffsetVector *= 0.1;\n"
615 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
616 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
617 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
618 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
619 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
620 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
621 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
622 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
623 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
624 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
625 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
626 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
627 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
628 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
631 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
632 " // this basically moves forward the full distance, and then backs up based\n"
633 " // on height of samples\n"
634 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
635 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
636 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
637 " TexCoord += OffsetVector;\n"
638 " OffsetVector *= 0.333;\n"
639 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
640 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
642 " return TexCoord;\n"
649 "#ifdef USEOFFSETMAPPING\n"
650 " // apply offsetmapping\n"
651 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
652 "#define TexCoord TexCoordOffset\n"
655 " // combine the diffuse textures (base, pants, shirt)\n"
656 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
657 "#ifdef USECOLORMAPPING\n"
658 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
664 "#ifdef MODE_LIGHTSOURCE\n"
667 " // calculate surface normal, light normal, and specular normal\n"
668 " // compute color intensity for the two textures (colormap and glossmap)\n"
669 " // scale by light color and attenuation as efficiently as possible\n"
670 " // (do as much scalar math as possible rather than vector math)\n"
671 "# ifdef USESPECULAR\n"
672 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
673 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
674 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
676 " // calculate directional shading\n"
677 " 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"
679 "# ifdef USEDIFFUSE\n"
680 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
681 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
683 " // calculate directional shading\n"
684 " 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"
686 " // calculate directionless shading\n"
687 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
691 "# ifdef USECUBEFILTER\n"
692 " // apply light cubemap filter\n"
693 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
694 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
696 " color *= myhvec4(gl_Color);\n"
697 "#endif // MODE_LIGHTSOURCE\n"
702 "#ifdef MODE_LIGHTDIRECTION\n"
703 " // directional model lighting\n"
705 " // get the surface normal and light normal\n"
706 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
707 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
709 " // calculate directional shading\n"
710 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
711 "# ifdef USESPECULAR\n"
712 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
713 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
715 " color *= myhvec4(gl_Color);\n"
716 "#endif // MODE_LIGHTDIRECTION\n"
721 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
722 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
724 " // get the surface normal and light normal\n"
725 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
727 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
728 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
729 " // calculate directional shading\n"
730 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
731 "# ifdef USESPECULAR\n"
732 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
733 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
736 " // apply lightmap color\n"
737 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
738 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
743 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
744 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
746 " // get the surface normal and light normal\n"
747 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
749 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
750 " // calculate directional shading\n"
751 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
752 "# ifdef USESPECULAR\n"
753 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
754 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
757 " // apply lightmap color\n"
758 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
759 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
764 "#ifdef MODE_LIGHTMAP\n"
765 " // apply lightmap color\n"
766 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
767 "#endif // MODE_LIGHTMAP\n"
776 "#ifdef MODE_LIGHTSOURCE\n"
778 " color.rgb *= color.a;\n"
782 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
783 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
784 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
785 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0));\n"
786 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
788 "# ifdef USEREFLECTION\n"
789 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
790 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
791 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
792 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw));\n"
798 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
803 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
806 "#ifdef USECONTRASTBOOST\n"
807 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
809 " color.rgb *= SceneBrightness;\n"
812 " gl_FragColor = vec4(color);\n"
815 "#endif // FRAGMENT_SHADER\n"
818 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
819 const char *permutationinfo[][2] =
821 {"#define MODE_LIGHTMAP\n", " lightmap"},
822 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
823 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
824 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
825 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
826 {"#define USEWATER\n", " water"},
827 {"#define USEREFLECTION\n", " reflection"},
828 {"#define USEGLOW\n", " glow"},
829 {"#define USEFOG\n", " fog"},
830 {"#define USECOLORMAPPING\n", " colormapping"},
831 {"#define USEDIFFUSE\n", " diffuse"},
832 {"#define USECONTRASTBOOST\n", " contrastboost"},
833 {"#define USESPECULAR\n", " specular"},
834 {"#define USECUBEFILTER\n", " cubefilter"},
835 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
836 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
840 void R_GLSL_CompilePermutation(const char *filename, int permutation)
843 qboolean shaderfound;
844 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
845 int vertstrings_count;
846 int geomstrings_count;
847 int fragstrings_count;
849 const char *vertstrings_list[32+1];
850 const char *geomstrings_list[32+1];
851 const char *fragstrings_list[32+1];
852 char permutationname[256];
857 vertstrings_list[0] = "#define VERTEX_SHADER\n";
858 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
859 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
860 vertstrings_count = 1;
861 geomstrings_count = 1;
862 fragstrings_count = 1;
863 permutationname[0] = 0;
864 for (i = 0;permutationinfo[i][0];i++)
866 if (permutation & (1<<i))
868 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
869 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
870 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
871 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
875 // keep line numbers correct
876 vertstrings_list[vertstrings_count++] = "\n";
877 geomstrings_list[geomstrings_count++] = "\n";
878 fragstrings_list[fragstrings_count++] = "\n";
881 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
885 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
886 vertstrings_list[vertstrings_count++] = shaderstring;
887 geomstrings_list[geomstrings_count++] = shaderstring;
888 fragstrings_list[fragstrings_count++] = shaderstring;
891 else if (!strcmp(filename, "glsl/default.glsl"))
893 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
894 vertstrings_list[vertstrings_count++] = builtinshaderstring;
895 geomstrings_list[geomstrings_count++] = builtinshaderstring;
896 fragstrings_list[fragstrings_count++] = builtinshaderstring;
899 // clear any lists that are not needed by this shader
900 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
901 vertstrings_count = 0;
902 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
903 geomstrings_count = 0;
904 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
905 fragstrings_count = 0;
906 // compile the shader program
907 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
908 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
912 qglUseProgramObjectARB(p->program);CHECKGLERROR
913 // look up all the uniform variable names we care about, so we don't
914 // have to look them up every time we set them
915 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
916 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
917 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
918 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
919 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
920 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
921 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
922 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
923 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
924 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
925 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
926 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
927 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
928 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
929 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
930 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
931 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
932 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
933 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
934 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
935 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
936 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
937 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
938 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
939 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
940 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
941 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
942 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
943 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
944 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
945 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
946 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
947 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
948 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
949 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
950 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
951 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
952 // initialize the samplers to refer to the texture units we use
953 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
954 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
955 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
956 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
957 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
958 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
959 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
960 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
961 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
962 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
963 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
964 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
965 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
967 qglUseProgramObjectARB(0);CHECKGLERROR
970 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
972 Mem_Free(shaderstring);
975 void R_GLSL_Restart_f(void)
978 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
979 if (r_glsl_permutations[i].program)
980 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
981 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
984 void R_GLSL_DumpShader_f(void)
988 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
991 Con_Printf("failed to write to glsl/default.glsl\n");
995 FS_Print(file, "// The engine may define the following macros:\n");
996 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
997 for (i = 0;permutationinfo[i][0];i++)
998 FS_Printf(file, "// %s", permutationinfo[i][0]);
999 FS_Print(file, "\n");
1000 FS_Print(file, builtinshaderstring);
1003 Con_Printf("glsl/default.glsl written\n");
1006 extern rtexture_t *r_shadow_attenuationgradienttexture;
1007 extern rtexture_t *r_shadow_attenuation2dtexture;
1008 extern rtexture_t *r_shadow_attenuation3dtexture;
1009 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1011 // select a permutation of the lighting shader appropriate to this
1012 // combination of texture, entity, light source, and fogging, only use the
1013 // minimum features necessary to avoid wasting rendering time in the
1014 // fragment shader on features that are not being used
1015 const char *shaderfilename = NULL;
1016 unsigned int permutation = 0;
1018 r_glsl_permutation = NULL;
1019 // TODO: implement geometry-shader based shadow volumes someday
1020 if (rsurface.rtlight)
1023 shaderfilename = "glsl/default.glsl";
1024 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1025 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1026 permutation |= SHADERPERMUTATION_CUBEFILTER;
1027 if (diffusescale > 0)
1028 permutation |= SHADERPERMUTATION_DIFFUSE;
1029 if (specularscale > 0)
1030 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1031 if (r_refdef.fogenabled)
1032 permutation |= SHADERPERMUTATION_FOG;
1033 if (rsurface.texture->colormapping)
1034 permutation |= SHADERPERMUTATION_COLORMAPPING;
1035 if (r_glsl_offsetmapping.integer)
1037 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1038 if (r_glsl_offsetmapping_reliefmapping.integer)
1039 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1041 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1042 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1043 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1044 permutation |= SHADERPERMUTATION_WATER;
1045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1046 permutation |= SHADERPERMUTATION_REFLECTION;
1048 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1050 // bright unshaded geometry
1051 shaderfilename = "glsl/default.glsl";
1052 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1053 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1054 if (rsurface.texture->currentskinframe->glow)
1055 permutation |= SHADERPERMUTATION_GLOW;
1056 if (r_refdef.fogenabled)
1057 permutation |= SHADERPERMUTATION_FOG;
1058 if (rsurface.texture->colormapping)
1059 permutation |= SHADERPERMUTATION_COLORMAPPING;
1060 if (r_glsl_offsetmapping.integer)
1062 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1063 if (r_glsl_offsetmapping_reliefmapping.integer)
1064 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1066 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1067 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1069 permutation |= SHADERPERMUTATION_WATER;
1070 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1071 permutation |= SHADERPERMUTATION_REFLECTION;
1073 else if (modellighting)
1075 // directional model lighting
1076 shaderfilename = "glsl/default.glsl";
1077 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1078 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1079 if (rsurface.texture->currentskinframe->glow)
1080 permutation |= SHADERPERMUTATION_GLOW;
1081 if (specularscale > 0)
1082 permutation |= SHADERPERMUTATION_SPECULAR;
1083 if (r_refdef.fogenabled)
1084 permutation |= SHADERPERMUTATION_FOG;
1085 if (rsurface.texture->colormapping)
1086 permutation |= SHADERPERMUTATION_COLORMAPPING;
1087 if (r_glsl_offsetmapping.integer)
1089 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1090 if (r_glsl_offsetmapping_reliefmapping.integer)
1091 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1093 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1094 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1096 permutation |= SHADERPERMUTATION_WATER;
1097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1098 permutation |= SHADERPERMUTATION_REFLECTION;
1103 shaderfilename = "glsl/default.glsl";
1104 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1105 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1107 // deluxemapping (light direction texture)
1108 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1109 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1111 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1112 if (specularscale > 0)
1113 permutation |= SHADERPERMUTATION_SPECULAR;
1115 else if (r_glsl_deluxemapping.integer >= 2)
1117 // fake deluxemapping (uniform light direction in tangentspace)
1118 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1119 if (specularscale > 0)
1120 permutation |= SHADERPERMUTATION_SPECULAR;
1124 // ordinary lightmapping
1125 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1127 if (rsurface.texture->currentskinframe->glow)
1128 permutation |= SHADERPERMUTATION_GLOW;
1129 if (r_refdef.fogenabled)
1130 permutation |= SHADERPERMUTATION_FOG;
1131 if (rsurface.texture->colormapping)
1132 permutation |= SHADERPERMUTATION_COLORMAPPING;
1133 if (r_glsl_offsetmapping.integer)
1135 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1136 if (r_glsl_offsetmapping_reliefmapping.integer)
1137 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1139 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1140 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1142 permutation |= SHADERPERMUTATION_WATER;
1143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1144 permutation |= SHADERPERMUTATION_REFLECTION;
1146 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1148 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1149 R_GLSL_CompilePermutation(shaderfilename, permutation);
1150 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1152 // remove features until we find a valid permutation
1154 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1158 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");
1159 Cvar_SetValueQuick(&r_glsl, 0);
1160 return 0; // no bit left to clear
1162 // reduce i more quickly whenever it would not remove any bits
1163 if (!(permutation & i))
1166 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1167 R_GLSL_CompilePermutation(shaderfilename, permutation);
1168 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1173 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1175 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1176 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1177 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1179 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1180 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1181 if (permutation & SHADERPERMUTATION_DIFFUSE)
1183 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1184 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1185 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1186 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1190 // ambient only is simpler
1191 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1192 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1193 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1194 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1197 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1199 if (r_glsl_permutation->loc_AmbientColor >= 0)
1200 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1201 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1202 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1203 if (r_glsl_permutation->loc_SpecularColor >= 0)
1204 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1205 if (r_glsl_permutation->loc_LightDir >= 0)
1206 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1210 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1211 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1212 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1214 nmap = rsurface.texture->currentskinframe->nmap;
1215 if (gl_lightmaps.integer)
1216 nmap = r_texture_blanknormalmap;
1217 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1218 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1219 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1220 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1221 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1222 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1223 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1224 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1225 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1226 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1227 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1228 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1229 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1230 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1231 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1233 // The formula used is actually:
1234 // color.rgb *= SceneBrightness;
1235 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1236 // I simplify that to
1237 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1238 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1240 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1241 // and do [[calculations]] here in the engine
1242 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1243 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1246 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1247 if (r_glsl_permutation->loc_FogColor >= 0)
1249 // additive passes are only darkened by fog, not tinted
1250 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1251 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1253 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1255 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1256 if (r_glsl_permutation->loc_Color_Pants >= 0)
1258 if (rsurface.texture->currentskinframe->pants)
1259 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1261 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1263 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1265 if (rsurface.texture->currentskinframe->shirt)
1266 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1268 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1270 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1271 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1272 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1273 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value, r_glsl_water_refractdistort.value, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value);
1274 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]);
1275 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]);
1276 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_RefractColor, r_glsl_water_refractcolor_r.value, r_glsl_water_refractcolor_g.value, r_glsl_water_refractcolor_b.value);
1277 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_ReflectColor, r_glsl_water_reflectcolor_r.value, r_glsl_water_reflectcolor_g.value, r_glsl_water_reflectcolor_b.value);
1282 void R_SwitchSurfaceShader(int permutation)
1284 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1286 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1288 qglUseProgramObjectARB(r_glsl_permutation->program);
1293 #define SKINFRAME_HASH 1024
1297 int loadsequence; // incremented each level change
1298 memexpandablearray_t array;
1299 skinframe_t *hash[SKINFRAME_HASH];
1303 void R_SkinFrame_PrepareForPurge(void)
1305 r_skinframe.loadsequence++;
1306 // wrap it without hitting zero
1307 if (r_skinframe.loadsequence >= 200)
1308 r_skinframe.loadsequence = 1;
1311 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1315 // mark the skinframe as used for the purging code
1316 skinframe->loadsequence = r_skinframe.loadsequence;
1319 void R_SkinFrame_Purge(void)
1323 for (i = 0;i < SKINFRAME_HASH;i++)
1325 for (s = r_skinframe.hash[i];s;s = s->next)
1327 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1329 if (s->base == r_texture_notexture) s->base = NULL;
1330 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1331 if (s->merged == s->base) s->merged = NULL;
1332 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1333 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1334 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1335 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1336 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1337 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1338 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1339 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1340 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1341 s->loadsequence = 0;
1347 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1351 char basename[MAX_QPATH];
1353 Image_StripImageExtension(name, basename, sizeof(basename));
1355 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1356 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1357 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1363 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1364 memset(item, 0, sizeof(*item));
1365 strlcpy(item->basename, basename, sizeof(item->basename));
1366 item->textureflags = textureflags;
1367 item->comparewidth = comparewidth;
1368 item->compareheight = compareheight;
1369 item->comparecrc = comparecrc;
1370 item->next = r_skinframe.hash[hashindex];
1371 r_skinframe.hash[hashindex] = item;
1373 R_SkinFrame_MarkUsed(item);
1377 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1379 // FIXME: it should be possible to disable loading various layers using
1380 // cvars, to prevent wasted loading time and memory usage if the user does
1382 qboolean loadnormalmap = true;
1383 qboolean loadgloss = true;
1384 qboolean loadpantsandshirt = true;
1385 qboolean loadglow = true;
1387 unsigned char *pixels;
1388 unsigned char *bumppixels;
1389 unsigned char *basepixels = NULL;
1390 int basepixels_width;
1391 int basepixels_height;
1392 skinframe_t *skinframe;
1394 if (cls.state == ca_dedicated)
1397 // return an existing skinframe if already loaded
1398 // if loading of the first image fails, don't make a new skinframe as it
1399 // would cause all future lookups of this to be missing
1400 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1401 if (skinframe && skinframe->base)
1404 basepixels = loadimagepixels(name, complain, 0, 0);
1405 if (basepixels == NULL)
1408 // we've got some pixels to store, so really allocate this new texture now
1410 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1411 skinframe->stain = NULL;
1412 skinframe->merged = NULL;
1413 skinframe->base = r_texture_notexture;
1414 skinframe->pants = NULL;
1415 skinframe->shirt = NULL;
1416 skinframe->nmap = r_texture_blanknormalmap;
1417 skinframe->gloss = NULL;
1418 skinframe->glow = NULL;
1419 skinframe->fog = NULL;
1421 basepixels_width = image_width;
1422 basepixels_height = image_height;
1423 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);
1425 if (textureflags & TEXF_ALPHA)
1427 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1428 if (basepixels[j] < 255)
1430 if (j < basepixels_width * basepixels_height * 4)
1432 // has transparent pixels
1433 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1434 for (j = 0;j < image_width * image_height * 4;j += 4)
1439 pixels[j+3] = basepixels[j+3];
1441 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);
1446 // _norm is the name used by tenebrae and has been adopted as standard
1449 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1451 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);
1455 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1457 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1458 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1459 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);
1461 Mem_Free(bumppixels);
1463 else if (r_shadow_bumpscale_basetexture.value > 0)
1465 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1466 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1467 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);
1471 // _luma is supported for tenebrae compatibility
1472 // (I think it's a very stupid name, but oh well)
1473 // _glow is the preferred name
1474 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1475 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1476 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1477 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1480 Mem_Free(basepixels);
1485 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)
1490 for (i = 0;i < width*height;i++)
1491 if (((unsigned char *)&palette[in[i]])[3] > 0)
1493 if (i == width*height)
1496 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1499 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)
1502 unsigned char *temp1, *temp2;
1503 skinframe_t *skinframe;
1505 if (cls.state == ca_dedicated)
1508 // if already loaded just return it, otherwise make a new skinframe
1509 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1510 if (skinframe && skinframe->base)
1513 skinframe->stain = NULL;
1514 skinframe->merged = NULL;
1515 skinframe->base = r_texture_notexture;
1516 skinframe->pants = NULL;
1517 skinframe->shirt = NULL;
1518 skinframe->nmap = r_texture_blanknormalmap;
1519 skinframe->gloss = NULL;
1520 skinframe->glow = NULL;
1521 skinframe->fog = NULL;
1523 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1527 if (bitsperpixel == 32)
1529 if (r_shadow_bumpscale_basetexture.value > 0)
1531 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1532 temp2 = temp1 + width * height * 4;
1533 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1534 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1537 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1538 if (textureflags & TEXF_ALPHA)
1540 for (i = 3;i < width * height * 4;i += 4)
1541 if (skindata[i] < 255)
1543 if (i < width * height * 4)
1545 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1546 memcpy(fogpixels, skindata, width * height * 4);
1547 for (i = 0;i < width * height * 4;i += 4)
1548 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1549 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1550 Mem_Free(fogpixels);
1554 else if (bitsperpixel == 8)
1556 if (r_shadow_bumpscale_basetexture.value > 0)
1558 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1559 temp2 = temp1 + width * height * 4;
1560 if (bitsperpixel == 32)
1561 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1564 // use either a custom palette or the quake palette
1565 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1566 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1568 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1571 // use either a custom palette, or the quake palette
1572 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
1573 if (!palette && loadglowtexture)
1574 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1575 if (!palette && loadpantsandshirt)
1577 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1578 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1580 if (skinframe->pants || skinframe->shirt)
1581 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1582 if (textureflags & TEXF_ALPHA)
1584 // if not using a custom alphapalette, use the quake one
1586 alphapalette = palette_alpha;
1587 for (i = 0;i < width * height;i++)
1588 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1590 if (i < width * height)
1591 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1598 skinframe_t *R_SkinFrame_LoadMissing(void)
1600 skinframe_t *skinframe;
1602 if (cls.state == ca_dedicated)
1605 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1606 skinframe->stain = NULL;
1607 skinframe->merged = NULL;
1608 skinframe->base = r_texture_notexture;
1609 skinframe->pants = NULL;
1610 skinframe->shirt = NULL;
1611 skinframe->nmap = r_texture_blanknormalmap;
1612 skinframe->gloss = NULL;
1613 skinframe->glow = NULL;
1614 skinframe->fog = NULL;
1619 void gl_main_start(void)
1624 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1625 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1627 alpha = 1 - exp(r / ((double)x*(double)x));
1628 if (x == FOGMASKTABLEWIDTH - 1)
1630 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1633 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1634 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1636 // set up r_skinframe loading system for textures
1637 memset(&r_skinframe, 0, sizeof(r_skinframe));
1638 r_skinframe.loadsequence = 1;
1639 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1641 r_main_texturepool = R_AllocTexturePool();
1642 R_BuildBlankTextures();
1644 if (gl_texturecubemap)
1647 R_BuildNormalizationCube();
1649 R_BuildFogTexture();
1650 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1651 memset(&r_waterstate, 0, sizeof(r_waterstate));
1652 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1653 memset(&r_svbsp, 0, sizeof (r_svbsp));
1656 void gl_main_shutdown(void)
1658 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1659 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1661 // clear out the r_skinframe state
1662 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1663 memset(&r_skinframe, 0, sizeof(r_skinframe));
1666 Mem_Free(r_svbsp.nodes);
1667 memset(&r_svbsp, 0, sizeof (r_svbsp));
1668 R_FreeTexturePool(&r_main_texturepool);
1669 r_texture_blanknormalmap = NULL;
1670 r_texture_white = NULL;
1671 r_texture_grey128 = NULL;
1672 r_texture_black = NULL;
1673 r_texture_whitecube = NULL;
1674 r_texture_normalizationcube = NULL;
1675 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1676 memset(&r_waterstate, 0, sizeof(r_waterstate));
1680 extern void CL_ParseEntityLump(char *entitystring);
1681 void gl_main_newmap(void)
1683 // FIXME: move this code to client
1685 char *entities, entname[MAX_QPATH];
1688 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1689 l = (int)strlen(entname) - 4;
1690 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1692 memcpy(entname + l, ".ent", 5);
1693 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1695 CL_ParseEntityLump(entities);
1700 if (cl.worldmodel->brush.entities)
1701 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1705 void GL_Main_Init(void)
1707 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1709 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1710 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1711 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1712 if (gamemode == GAME_NEHAHRA)
1714 Cvar_RegisterVariable (&gl_fogenable);
1715 Cvar_RegisterVariable (&gl_fogdensity);
1716 Cvar_RegisterVariable (&gl_fogred);
1717 Cvar_RegisterVariable (&gl_foggreen);
1718 Cvar_RegisterVariable (&gl_fogblue);
1719 Cvar_RegisterVariable (&gl_fogstart);
1720 Cvar_RegisterVariable (&gl_fogend);
1722 Cvar_RegisterVariable(&r_depthfirst);
1723 Cvar_RegisterVariable(&r_nearclip);
1724 Cvar_RegisterVariable(&r_showbboxes);
1725 Cvar_RegisterVariable(&r_showsurfaces);
1726 Cvar_RegisterVariable(&r_showtris);
1727 Cvar_RegisterVariable(&r_shownormals);
1728 Cvar_RegisterVariable(&r_showlighting);
1729 Cvar_RegisterVariable(&r_showshadowvolumes);
1730 Cvar_RegisterVariable(&r_showcollisionbrushes);
1731 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1732 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1733 Cvar_RegisterVariable(&r_showdisabledepthtest);
1734 Cvar_RegisterVariable(&r_drawportals);
1735 Cvar_RegisterVariable(&r_drawentities);
1736 Cvar_RegisterVariable(&r_cullentities_trace);
1737 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1738 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1739 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1740 Cvar_RegisterVariable(&r_drawviewmodel);
1741 Cvar_RegisterVariable(&r_speeds);
1742 Cvar_RegisterVariable(&r_fullbrights);
1743 Cvar_RegisterVariable(&r_wateralpha);
1744 Cvar_RegisterVariable(&r_dynamic);
1745 Cvar_RegisterVariable(&r_fullbright);
1746 Cvar_RegisterVariable(&r_shadows);
1747 Cvar_RegisterVariable(&r_shadows_throwdistance);
1748 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1749 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1750 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1751 Cvar_RegisterVariable(&r_textureunits);
1752 Cvar_RegisterVariable(&r_glsl);
1753 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1754 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1755 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1756 Cvar_RegisterVariable(&r_glsl_water);
1757 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1758 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1759 Cvar_RegisterVariable(&r_glsl_water_refractcolor_r);
1760 Cvar_RegisterVariable(&r_glsl_water_refractcolor_g);
1761 Cvar_RegisterVariable(&r_glsl_water_refractcolor_b);
1762 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_r);
1763 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_g);
1764 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_b);
1765 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1766 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1767 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1768 Cvar_RegisterVariable(&r_lerpsprites);
1769 Cvar_RegisterVariable(&r_lerpmodels);
1770 Cvar_RegisterVariable(&r_waterscroll);
1771 Cvar_RegisterVariable(&r_bloom);
1772 Cvar_RegisterVariable(&r_bloom_colorscale);
1773 Cvar_RegisterVariable(&r_bloom_brighten);
1774 Cvar_RegisterVariable(&r_bloom_blur);
1775 Cvar_RegisterVariable(&r_bloom_resolution);
1776 Cvar_RegisterVariable(&r_bloom_colorexponent);
1777 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1778 Cvar_RegisterVariable(&r_hdr);
1779 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1780 Cvar_RegisterVariable(&r_glsl_contrastboost);
1781 Cvar_RegisterVariable(&r_hdr_glowintensity);
1782 Cvar_RegisterVariable(&r_hdr_range);
1783 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1784 Cvar_RegisterVariable(&developer_texturelogging);
1785 Cvar_RegisterVariable(&gl_lightmaps);
1786 Cvar_RegisterVariable(&r_test);
1787 Cvar_RegisterVariable(&r_batchmode);
1788 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1789 Cvar_SetValue("r_fullbrights", 0);
1790 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1793 extern void R_Textures_Init(void);
1794 extern void GL_Draw_Init(void);
1795 extern void GL_Main_Init(void);
1796 extern void R_Shadow_Init(void);
1797 extern void R_Sky_Init(void);
1798 extern void GL_Surf_Init(void);
1799 extern void R_Light_Init(void);
1800 extern void R_Particles_Init(void);
1801 extern void R_Explosion_Init(void);
1802 extern void gl_backend_init(void);
1803 extern void Sbar_Init(void);
1804 extern void R_LightningBeams_Init(void);
1805 extern void Mod_RenderInit(void);
1807 void Render_Init(void)
1820 R_LightningBeams_Init();
1829 extern char *ENGINE_EXTENSIONS;
1832 VID_CheckExtensions();
1834 // LordHavoc: report supported extensions
1835 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1837 // clear to black (loading plaque will be seen over this)
1839 qglClearColor(0,0,0,1);CHECKGLERROR
1840 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1843 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1847 for (i = 0;i < r_view.numfrustumplanes;i++)
1849 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1852 p = r_view.frustum + i;
1857 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1861 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1865 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1869 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1873 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1877 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1881 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1885 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1893 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1897 for (i = 0;i < numplanes;i++)
1904 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1908 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1912 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1916 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1920 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1924 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1928 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1932 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1940 //==================================================================================
1942 static void R_UpdateEntityLighting(entity_render_t *ent)
1944 vec3_t tempdiffusenormal;
1946 // fetch the lighting from the worldmodel data
1947 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));
1948 VectorClear(ent->modellight_diffuse);
1949 VectorClear(tempdiffusenormal);
1950 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1953 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1954 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1957 VectorSet(ent->modellight_ambient, 1, 1, 1);
1959 // move the light direction into modelspace coordinates for lighting code
1960 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1961 if(VectorLength2(ent->modellight_lightdir) > 0)
1963 VectorNormalize(ent->modellight_lightdir);
1967 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1970 // scale ambient and directional light contributions according to rendering variables
1971 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1972 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1973 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1974 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1975 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1976 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1979 static void R_View_UpdateEntityVisible (void)
1982 entity_render_t *ent;
1984 if (!r_drawentities.integer)
1987 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1988 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1990 // worldmodel can check visibility
1991 for (i = 0;i < r_refdef.numentities;i++)
1993 ent = r_refdef.entities[i];
1994 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1996 if(r_cullentities_trace.integer)
1998 for (i = 0;i < r_refdef.numentities;i++)
2000 ent = r_refdef.entities[i];
2001 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2003 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2004 ent->last_trace_visibility = realtime;
2005 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2006 r_viewcache.entityvisible[i] = 0;
2013 // no worldmodel or it can't check visibility
2014 for (i = 0;i < r_refdef.numentities;i++)
2016 ent = r_refdef.entities[i];
2017 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2021 // update entity lighting (even on hidden entities for r_shadows)
2022 for (i = 0;i < r_refdef.numentities;i++)
2023 R_UpdateEntityLighting(r_refdef.entities[i]);
2026 // only used if skyrendermasked, and normally returns false
2027 int R_DrawBrushModelsSky (void)
2030 entity_render_t *ent;
2032 if (!r_drawentities.integer)
2036 for (i = 0;i < r_refdef.numentities;i++)
2038 if (!r_viewcache.entityvisible[i])
2040 ent = r_refdef.entities[i];
2041 if (!ent->model || !ent->model->DrawSky)
2043 ent->model->DrawSky(ent);
2049 static void R_DrawNoModel(entity_render_t *ent);
2050 static void R_DrawModels(void)
2053 entity_render_t *ent;
2055 if (!r_drawentities.integer)
2058 for (i = 0;i < r_refdef.numentities;i++)
2060 if (!r_viewcache.entityvisible[i])
2062 ent = r_refdef.entities[i];
2063 r_refdef.stats.entities++;
2064 if (ent->model && ent->model->Draw != NULL)
2065 ent->model->Draw(ent);
2071 static void R_DrawModelsDepth(void)
2074 entity_render_t *ent;
2076 if (!r_drawentities.integer)
2079 for (i = 0;i < r_refdef.numentities;i++)
2081 if (!r_viewcache.entityvisible[i])
2083 ent = r_refdef.entities[i];
2084 r_refdef.stats.entities++;
2085 if (ent->model && ent->model->DrawDepth != NULL)
2086 ent->model->DrawDepth(ent);
2090 static void R_DrawModelsAddWaterPlanes(void)
2093 entity_render_t *ent;
2095 if (!r_drawentities.integer)
2098 for (i = 0;i < r_refdef.numentities;i++)
2100 if (!r_viewcache.entityvisible[i])
2102 ent = r_refdef.entities[i];
2103 r_refdef.stats.entities++;
2104 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2105 ent->model->DrawAddWaterPlanes(ent);
2109 static void R_View_SetFrustum(void)
2112 double slopex, slopey;
2114 // break apart the view matrix into vectors for various purposes
2115 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2116 VectorNegate(r_view.left, r_view.right);
2119 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2120 r_view.frustum[0].normal[1] = 0 - 0;
2121 r_view.frustum[0].normal[2] = -1 - 0;
2122 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2123 r_view.frustum[1].normal[1] = 0 + 0;
2124 r_view.frustum[1].normal[2] = -1 + 0;
2125 r_view.frustum[2].normal[0] = 0 - 0;
2126 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2127 r_view.frustum[2].normal[2] = -1 - 0;
2128 r_view.frustum[3].normal[0] = 0 + 0;
2129 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2130 r_view.frustum[3].normal[2] = -1 + 0;
2134 zNear = r_refdef.nearclip;
2135 nudge = 1.0 - 1.0 / (1<<23);
2136 r_view.frustum[4].normal[0] = 0 - 0;
2137 r_view.frustum[4].normal[1] = 0 - 0;
2138 r_view.frustum[4].normal[2] = -1 - -nudge;
2139 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2140 r_view.frustum[5].normal[0] = 0 + 0;
2141 r_view.frustum[5].normal[1] = 0 + 0;
2142 r_view.frustum[5].normal[2] = -1 + -nudge;
2143 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2149 r_view.frustum[0].normal[0] = m[3] - m[0];
2150 r_view.frustum[0].normal[1] = m[7] - m[4];
2151 r_view.frustum[0].normal[2] = m[11] - m[8];
2152 r_view.frustum[0].dist = m[15] - m[12];
2154 r_view.frustum[1].normal[0] = m[3] + m[0];
2155 r_view.frustum[1].normal[1] = m[7] + m[4];
2156 r_view.frustum[1].normal[2] = m[11] + m[8];
2157 r_view.frustum[1].dist = m[15] + m[12];
2159 r_view.frustum[2].normal[0] = m[3] - m[1];
2160 r_view.frustum[2].normal[1] = m[7] - m[5];
2161 r_view.frustum[2].normal[2] = m[11] - m[9];
2162 r_view.frustum[2].dist = m[15] - m[13];
2164 r_view.frustum[3].normal[0] = m[3] + m[1];
2165 r_view.frustum[3].normal[1] = m[7] + m[5];
2166 r_view.frustum[3].normal[2] = m[11] + m[9];
2167 r_view.frustum[3].dist = m[15] + m[13];
2169 r_view.frustum[4].normal[0] = m[3] - m[2];
2170 r_view.frustum[4].normal[1] = m[7] - m[6];
2171 r_view.frustum[4].normal[2] = m[11] - m[10];
2172 r_view.frustum[4].dist = m[15] - m[14];
2174 r_view.frustum[5].normal[0] = m[3] + m[2];
2175 r_view.frustum[5].normal[1] = m[7] + m[6];
2176 r_view.frustum[5].normal[2] = m[11] + m[10];
2177 r_view.frustum[5].dist = m[15] + m[14];
2182 if (r_view.useperspective)
2184 slopex = 1.0 / r_view.frustum_x;
2185 slopey = 1.0 / r_view.frustum_y;
2186 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2187 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2188 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2189 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2190 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2192 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2193 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2194 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2195 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2196 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2198 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2199 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2200 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2201 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2202 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2206 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2207 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2208 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2209 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2210 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2211 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2212 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2213 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2214 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2215 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2217 r_view.numfrustumplanes = 5;
2219 if (r_view.useclipplane)
2221 r_view.numfrustumplanes = 6;
2222 r_view.frustum[5] = r_view.clipplane;
2225 for (i = 0;i < r_view.numfrustumplanes;i++)
2226 PlaneClassify(r_view.frustum + i);
2228 // LordHavoc: note to all quake engine coders, Quake had a special case
2229 // for 90 degrees which assumed a square view (wrong), so I removed it,
2230 // Quake2 has it disabled as well.
2232 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2233 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2234 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2235 //PlaneClassify(&frustum[0]);
2237 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2238 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2239 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2240 //PlaneClassify(&frustum[1]);
2242 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2243 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2244 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2245 //PlaneClassify(&frustum[2]);
2247 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2248 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2249 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2250 //PlaneClassify(&frustum[3]);
2253 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2254 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2255 //PlaneClassify(&frustum[4]);
2258 void R_View_Update(void)
2260 R_View_SetFrustum();
2261 R_View_WorldVisibility(r_view.useclipplane);
2262 R_View_UpdateEntityVisible();
2265 void R_SetupView(void)
2267 if (!r_view.useperspective)
2268 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);
2269 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2270 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2272 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2274 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2276 if (r_view.useclipplane)
2278 // LordHavoc: couldn't figure out how to make this approach the
2279 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2280 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2281 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2282 dist = r_view.clipplane.dist;
2283 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2287 void R_ResetViewRendering2D(void)
2289 if (gl_support_fragment_shader)
2291 qglUseProgramObjectARB(0);CHECKGLERROR
2296 // GL is weird because it's bottom to top, r_view.y is top to bottom
2297 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2298 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2299 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2300 GL_Color(1, 1, 1, 1);
2301 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2302 GL_BlendFunc(GL_ONE, GL_ZERO);
2303 GL_AlphaTest(false);
2304 GL_ScissorTest(false);
2305 GL_DepthMask(false);
2306 GL_DepthRange(0, 1);
2307 GL_DepthTest(false);
2308 R_Mesh_Matrix(&identitymatrix);
2309 R_Mesh_ResetTextureState();
2310 GL_PolygonOffset(0, 0);
2311 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2312 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2313 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2314 qglStencilMask(~0);CHECKGLERROR
2315 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2316 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2317 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2320 void R_ResetViewRendering3D(void)
2322 if (gl_support_fragment_shader)
2324 qglUseProgramObjectARB(0);CHECKGLERROR
2329 // GL is weird because it's bottom to top, r_view.y is top to bottom
2330 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2332 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2333 GL_Color(1, 1, 1, 1);
2334 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2335 GL_BlendFunc(GL_ONE, GL_ZERO);
2336 GL_AlphaTest(false);
2337 GL_ScissorTest(true);
2339 GL_DepthRange(0, 1);
2341 R_Mesh_Matrix(&identitymatrix);
2342 R_Mesh_ResetTextureState();
2343 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2344 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2345 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2346 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2347 qglStencilMask(~0);CHECKGLERROR
2348 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2349 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2350 GL_CullFace(r_view.cullface_back);
2354 R_Bloom_SetupShader(
2356 "// written by Forest 'LordHavoc' Hale\n"
2358 "// common definitions between vertex shader and fragment shader:\n"
2360 "#ifdef __GLSL_CG_DATA_TYPES\n"
2361 "#define myhalf half\n"
2362 "#define myhvec2 hvec2\n"
2363 "#define myhvec3 hvec3\n"
2364 "#define myhvec4 hvec4\n"
2366 "#define myhalf float\n"
2367 "#define myhvec2 vec2\n"
2368 "#define myhvec3 vec3\n"
2369 "#define myhvec4 vec4\n"
2372 "varying vec2 ScreenTexCoord;\n"
2373 "varying vec2 BloomTexCoord;\n"
2378 "// vertex shader specific:\n"
2379 "#ifdef VERTEX_SHADER\n"
2383 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2384 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2385 " // transform vertex to camera space, using ftransform to match non-VS\n"
2387 " gl_Position = ftransform();\n"
2390 "#endif // VERTEX_SHADER\n"
2395 "// fragment shader specific:\n"
2396 "#ifdef FRAGMENT_SHADER\n"
2401 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2402 " for (x = -BLUR_X;x <= BLUR_X;x++)
2403 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2404 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2405 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2406 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2408 " gl_FragColor = vec4(color);\n"
2411 "#endif // FRAGMENT_SHADER\n"
2414 void R_RenderScene(qboolean addwaterplanes);
2416 static void R_Water_StartFrame(void)
2419 int texturewidth, textureheight;
2420 r_waterstate_waterplane_t *p;
2422 r_waterstate.maxwaterplanes = 0;
2424 // set waterwidth and waterheight to the water resolution that will be
2425 // used (often less than the screen resolution for faster rendering)
2426 r_waterstate.waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2427 r_waterstate.waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2429 // calculate desired texture sizes
2430 if (gl_support_arb_texture_non_power_of_two)
2432 texturewidth = r_waterstate.waterwidth;
2433 textureheight = r_waterstate.waterheight;
2437 for (texturewidth = 1;texturewidth < r_waterstate.waterwidth ;texturewidth *= 2);
2438 for (textureheight = 1;textureheight < r_waterstate.waterheight;textureheight *= 2);
2441 if (!r_glsl_water.integer)
2442 texturewidth = textureheight = 0;
2444 // allocate textures as needed
2445 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2447 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2449 if (p->texture_refraction)
2450 R_FreeTexture(p->texture_refraction);
2451 p->texture_refraction = NULL;
2452 if (p->texture_reflection)
2453 R_FreeTexture(p->texture_reflection);
2454 p->texture_reflection = NULL;
2456 r_waterstate.texturewidth = texturewidth;
2457 r_waterstate.textureheight = textureheight;
2460 if ((!texturewidth && !textureheight) || texturewidth > gl_max_texture_size || textureheight > gl_max_texture_size)
2462 // can't use water if the parameters are too weird
2463 // can't use water if the card does not support the texture size
2464 memset(&r_waterstate, 0, sizeof(r_waterstate));
2468 r_waterstate.enabled = true;
2470 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2472 // set up variables that will be used in shader setup
2473 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2474 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2475 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2476 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2479 static void R_Water_AddWaterPlane(msurface_t *surface)
2481 int triangleindex, planeindex;
2485 r_waterstate_waterplane_t *p;
2486 // just use the first triangle with a valid normal for any decisions
2487 VectorClear(normal);
2488 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2490 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2491 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2492 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2493 TriangleNormal(vert[0], vert[1], vert[2], normal);
2494 if (VectorLength2(normal) >= 0.001)
2497 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2499 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2501 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2505 // if this triangle does not fit any known plane rendered this frame, render textures for it
2506 if (planeindex >= r_waterstate.numwaterplanes && planeindex < r_waterstate.maxwaterplanes)
2508 // store the new plane
2509 r_waterstate.numwaterplanes++;
2510 VectorCopy(normal, p->plane.normal);
2511 VectorNormalize(p->plane.normal);
2512 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2513 PlaneClassify(&p->plane);
2514 // flip the plane if it does not face the viewer
2515 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2517 VectorNegate(p->plane.normal, p->plane.normal);
2518 p->plane.dist *= -1;
2519 PlaneClassify(&p->plane);
2521 p->materialflags = surface->texture->currentframe->currentmaterialflags;
2525 static void R_Water_ProcessPlanes(void)
2527 r_view_t originalview;
2529 r_waterstate_waterplane_t *p;
2531 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2533 if (!p->texture_refraction && (p->materialflags & MATERIALFLAG_WATERSHADER))
2534 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);
2535 if (!p->texture_reflection && (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
2536 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);
2538 originalview = r_view;
2539 r_view.showdebug = false;
2540 r_view.width = r_waterstate.waterwidth;
2541 r_view.height = r_waterstate.waterheight;
2542 r_view.useclipplane = true;
2544 r_view.clipplane = p->plane;
2545 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2546 r_view.clipplane.dist = -r_view.clipplane.dist;
2547 PlaneClassify(&r_view.clipplane);
2548 r_waterstate.renderingscene = true;
2549 // render the normal view scene and copy into texture
2550 // (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)
2551 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2553 R_RenderScene(false);
2555 // copy view into the screen texture
2556 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2557 GL_ActiveTexture(0);
2559 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
2562 // render reflected scene and copy into texture
2563 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2564 r_view.clipplane = p->plane;
2565 // reverse the cullface settings for this render
2566 r_view.cullface_front = GL_FRONT;
2567 r_view.cullface_back = GL_BACK;
2569 R_ResetViewRendering3D();
2572 R_RenderScene(false);
2574 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2575 GL_ActiveTexture(0);
2577 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
2579 R_ResetViewRendering3D();
2582 r_view = originalview;
2583 r_waterstate.renderingscene = false;
2587 void R_Bloom_StartFrame(void)
2589 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2591 // set bloomwidth and bloomheight to the bloom resolution that will be
2592 // used (often less than the screen resolution for faster rendering)
2593 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2594 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2595 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2597 // calculate desired texture sizes
2598 if (gl_support_arb_texture_non_power_of_two)
2600 screentexturewidth = r_view.width;
2601 screentextureheight = r_view.height;
2602 bloomtexturewidth = r_bloomstate.bloomwidth;
2603 bloomtextureheight = r_bloomstate.bloomheight;
2607 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2608 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2609 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2610 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2615 screentexturewidth = screentextureheight = 0;
2617 else if (r_bloom.integer)
2622 screentexturewidth = screentextureheight = 0;
2623 bloomtexturewidth = bloomtextureheight = 0;
2626 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)
2628 // can't use bloom if the parameters are too weird
2629 // can't use bloom if the card does not support the texture size
2630 if (r_bloomstate.texture_screen)
2631 R_FreeTexture(r_bloomstate.texture_screen);
2632 if (r_bloomstate.texture_bloom)
2633 R_FreeTexture(r_bloomstate.texture_bloom);
2634 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2638 r_bloomstate.enabled = true;
2639 r_bloomstate.hdr = r_hdr.integer != 0;
2641 // allocate textures as needed
2642 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2644 if (r_bloomstate.texture_screen)
2645 R_FreeTexture(r_bloomstate.texture_screen);
2646 r_bloomstate.texture_screen = NULL;
2647 r_bloomstate.screentexturewidth = screentexturewidth;
2648 r_bloomstate.screentextureheight = screentextureheight;
2649 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2650 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);
2652 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2654 if (r_bloomstate.texture_bloom)
2655 R_FreeTexture(r_bloomstate.texture_bloom);
2656 r_bloomstate.texture_bloom = NULL;
2657 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2658 r_bloomstate.bloomtextureheight = bloomtextureheight;
2659 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2660 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);
2663 // set up a texcoord array for the full resolution screen image
2664 // (we have to keep this around to copy back during final render)
2665 r_bloomstate.screentexcoord2f[0] = 0;
2666 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2667 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2668 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2669 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2670 r_bloomstate.screentexcoord2f[5] = 0;
2671 r_bloomstate.screentexcoord2f[6] = 0;
2672 r_bloomstate.screentexcoord2f[7] = 0;
2674 // set up a texcoord array for the reduced resolution bloom image
2675 // (which will be additive blended over the screen image)
2676 r_bloomstate.bloomtexcoord2f[0] = 0;
2677 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2678 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2679 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2680 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2681 r_bloomstate.bloomtexcoord2f[5] = 0;
2682 r_bloomstate.bloomtexcoord2f[6] = 0;
2683 r_bloomstate.bloomtexcoord2f[7] = 0;
2686 void R_Bloom_CopyScreenTexture(float colorscale)
2688 r_refdef.stats.bloom++;
2690 R_ResetViewRendering2D();
2691 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2692 R_Mesh_ColorPointer(NULL, 0, 0);
2693 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2694 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2696 // copy view into the screen texture
2697 GL_ActiveTexture(0);
2699 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
2700 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2702 // now scale it down to the bloom texture size
2704 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2705 GL_BlendFunc(GL_ONE, GL_ZERO);
2706 GL_Color(colorscale, colorscale, colorscale, 1);
2707 // TODO: optimize with multitexture or GLSL
2708 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2709 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2711 // we now have a bloom image in the framebuffer
2712 // copy it into the bloom image texture for later processing
2713 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2714 GL_ActiveTexture(0);
2716 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
2717 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2720 void R_Bloom_CopyHDRTexture(void)
2722 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2723 GL_ActiveTexture(0);
2725 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
2726 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2729 void R_Bloom_MakeTexture(void)
2732 float xoffset, yoffset, r, brighten;
2734 r_refdef.stats.bloom++;
2736 R_ResetViewRendering2D();
2737 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2738 R_Mesh_ColorPointer(NULL, 0, 0);
2740 // we have a bloom image in the framebuffer
2742 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2744 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2747 r = bound(0, r_bloom_colorexponent.value / x, 1);
2748 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2749 GL_Color(r, r, r, 1);
2750 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2751 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2752 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2753 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2755 // copy the vertically blurred bloom view to a texture
2756 GL_ActiveTexture(0);
2758 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
2759 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2762 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2763 brighten = r_bloom_brighten.value;
2765 brighten *= r_hdr_range.value;
2766 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2767 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2769 for (dir = 0;dir < 2;dir++)
2771 // blend on at multiple vertical offsets to achieve a vertical blur
2772 // TODO: do offset blends using GLSL
2773 GL_BlendFunc(GL_ONE, GL_ZERO);
2774 for (x = -range;x <= range;x++)
2776 if (!dir){xoffset = 0;yoffset = x;}
2777 else {xoffset = x;yoffset = 0;}
2778 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2779 yoffset /= (float)r_bloomstate.bloomtextureheight;
2780 // compute a texcoord array with the specified x and y offset
2781 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2782 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2783 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2784 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2785 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2786 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2787 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2788 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2789 // this r value looks like a 'dot' particle, fading sharply to
2790 // black at the edges
2791 // (probably not realistic but looks good enough)
2792 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2793 //r = (dir ? 1.0f : brighten)/(range*2+1);
2794 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2795 GL_Color(r, r, r, 1);
2796 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2797 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2798 GL_BlendFunc(GL_ONE, GL_ONE);
2801 // copy the vertically blurred bloom view to a texture
2802 GL_ActiveTexture(0);
2804 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
2805 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2808 // apply subtract last
2809 // (just like it would be in a GLSL shader)
2810 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2812 GL_BlendFunc(GL_ONE, GL_ZERO);
2813 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2814 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2815 GL_Color(1, 1, 1, 1);
2816 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2817 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2819 GL_BlendFunc(GL_ONE, GL_ONE);
2820 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2821 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2822 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2823 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2824 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2825 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2826 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2828 // copy the darkened bloom view to a texture
2829 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2830 GL_ActiveTexture(0);
2832 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2833 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2837 void R_HDR_RenderBloomTexture(void)
2839 int oldwidth, oldheight;
2841 oldwidth = r_view.width;
2842 oldheight = r_view.height;
2843 r_view.width = r_bloomstate.bloomwidth;
2844 r_view.height = r_bloomstate.bloomheight;
2846 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2847 // TODO: add exposure compensation features
2848 // TODO: add fp16 framebuffer support
2850 r_view.showdebug = false;
2851 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2853 r_view.colorscale /= r_hdr_range.value;
2854 r_waterstate.numwaterplanes = 0;
2855 R_RenderScene(r_waterstate.enabled);
2856 r_view.showdebug = true;
2858 R_ResetViewRendering2D();
2860 R_Bloom_CopyHDRTexture();
2861 R_Bloom_MakeTexture();
2863 R_ResetViewRendering3D();
2866 if (r_timereport_active)
2867 R_TimeReport("clear");
2870 // restore the view settings
2871 r_view.width = oldwidth;
2872 r_view.height = oldheight;
2875 static void R_BlendView(void)
2877 if (r_bloomstate.enabled && r_bloomstate.hdr)
2879 // render high dynamic range bloom effect
2880 // the bloom texture was made earlier this render, so we just need to
2881 // blend it onto the screen...
2882 R_ResetViewRendering2D();
2883 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2884 R_Mesh_ColorPointer(NULL, 0, 0);
2885 GL_Color(1, 1, 1, 1);
2886 GL_BlendFunc(GL_ONE, GL_ONE);
2887 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2888 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2889 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2890 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2892 else if (r_bloomstate.enabled)
2894 // render simple bloom effect
2895 // copy the screen and shrink it and darken it for the bloom process
2896 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2897 // make the bloom texture
2898 R_Bloom_MakeTexture();
2899 // put the original screen image back in place and blend the bloom
2901 R_ResetViewRendering2D();
2902 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2903 R_Mesh_ColorPointer(NULL, 0, 0);
2904 GL_Color(1, 1, 1, 1);
2905 GL_BlendFunc(GL_ONE, GL_ZERO);
2906 // do both in one pass if possible
2907 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2908 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2909 if (r_textureunits.integer >= 2 && gl_combine.integer)
2911 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2912 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2913 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2917 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2918 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2919 // now blend on the bloom texture
2920 GL_BlendFunc(GL_ONE, GL_ONE);
2921 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2922 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2924 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2925 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2927 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2929 // apply a color tint to the whole view
2930 R_ResetViewRendering2D();
2931 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2932 R_Mesh_ColorPointer(NULL, 0, 0);
2933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2934 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2935 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2939 void R_RenderScene(qboolean addwaterplanes);
2941 matrix4x4_t r_waterscrollmatrix;
2943 void R_UpdateVariables(void)
2947 r_refdef.farclip = 4096;
2948 if (r_refdef.worldmodel)
2949 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2950 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2952 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2953 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2954 r_refdef.polygonfactor = 0;
2955 r_refdef.polygonoffset = 0;
2956 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2957 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2959 r_refdef.rtworld = r_shadow_realtime_world.integer;
2960 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2961 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2962 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2963 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2964 if (r_showsurfaces.integer)
2966 r_refdef.rtworld = false;
2967 r_refdef.rtworldshadows = false;
2968 r_refdef.rtdlight = false;
2969 r_refdef.rtdlightshadows = false;
2970 r_refdef.lightmapintensity = 0;
2973 if (gamemode == GAME_NEHAHRA)
2975 if (gl_fogenable.integer)
2977 r_refdef.oldgl_fogenable = true;
2978 r_refdef.fog_density = gl_fogdensity.value;
2979 r_refdef.fog_red = gl_fogred.value;
2980 r_refdef.fog_green = gl_foggreen.value;
2981 r_refdef.fog_blue = gl_fogblue.value;
2983 else if (r_refdef.oldgl_fogenable)
2985 r_refdef.oldgl_fogenable = false;
2986 r_refdef.fog_density = 0;
2987 r_refdef.fog_red = 0;
2988 r_refdef.fog_green = 0;
2989 r_refdef.fog_blue = 0;
2992 if (r_refdef.fog_density)
2994 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2995 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2996 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2998 if (r_refdef.fog_density)
3000 r_refdef.fogenabled = true;
3001 // this is the point where the fog reaches 0.9986 alpha, which we
3002 // consider a good enough cutoff point for the texture
3003 // (0.9986 * 256 == 255.6)
3004 r_refdef.fogrange = 400 / r_refdef.fog_density;
3005 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3006 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3007 // fog color was already set
3010 r_refdef.fogenabled = false;
3018 void R_RenderView(void)
3020 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3021 return; //Host_Error ("R_RenderView: NULL worldmodel");
3023 R_Shadow_UpdateWorldLightSelection();
3025 R_Bloom_StartFrame();
3026 R_Water_StartFrame();
3029 if (r_timereport_active)
3030 R_TimeReport("setup");
3032 R_ResetViewRendering3D();
3035 if (r_timereport_active)
3036 R_TimeReport("clear");
3038 r_view.showdebug = true;
3040 // this produces a bloom texture to be used in R_BlendView() later
3042 R_HDR_RenderBloomTexture();
3044 r_view.colorscale = r_hdr_scenebrightness.value;
3045 r_waterstate.numwaterplanes = 0;
3046 R_RenderScene(r_waterstate.enabled);
3049 if (r_timereport_active)
3050 R_TimeReport("blendview");
3052 GL_Scissor(0, 0, vid.width, vid.height);
3053 GL_ScissorTest(false);
3057 extern void R_DrawLightningBeams (void);
3058 extern void VM_CL_AddPolygonsToMeshQueue (void);
3059 extern void R_DrawPortals (void);
3060 extern cvar_t cl_locs_show;
3061 static void R_DrawLocs(void);
3062 static void R_DrawEntityBBoxes(void);
3063 void R_RenderScene(qboolean addwaterplanes)
3067 R_ResetViewRendering3D();
3070 if (r_timereport_active)
3071 R_TimeReport("watervisibility");
3073 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3075 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3076 if (r_timereport_active)
3077 R_TimeReport("waterworld");
3080 // don't let sound skip if going slow
3081 if (r_refdef.extraupdate)
3084 R_DrawModelsAddWaterPlanes();
3085 if (r_timereport_active)
3086 R_TimeReport("watermodels");
3088 R_Water_ProcessPlanes();
3089 if (r_timereport_active)
3090 R_TimeReport("waterscenes");
3093 R_ResetViewRendering3D();
3095 // don't let sound skip if going slow
3096 if (r_refdef.extraupdate)
3099 R_MeshQueue_BeginScene();
3104 if (r_timereport_active)
3105 R_TimeReport("visibility");
3107 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);
3109 if (cl.csqc_vidvars.drawworld)
3111 // don't let sound skip if going slow
3112 if (r_refdef.extraupdate)
3115 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3117 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3118 if (r_timereport_active)
3119 R_TimeReport("worldsky");
3122 if (R_DrawBrushModelsSky() && r_timereport_active)
3123 R_TimeReport("bmodelsky");
3126 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3128 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3129 if (r_timereport_active)
3130 R_TimeReport("worlddepth");
3132 if (r_depthfirst.integer >= 2)
3134 R_DrawModelsDepth();
3135 if (r_timereport_active)
3136 R_TimeReport("modeldepth");
3139 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3141 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3142 if (r_timereport_active)
3143 R_TimeReport("world");
3146 // don't let sound skip if going slow
3147 if (r_refdef.extraupdate)
3151 if (r_timereport_active)
3152 R_TimeReport("models");
3154 // don't let sound skip if going slow
3155 if (r_refdef.extraupdate)
3158 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3160 R_DrawModelShadows();
3162 R_ResetViewRendering3D();
3164 // don't let sound skip if going slow
3165 if (r_refdef.extraupdate)
3169 R_ShadowVolumeLighting(false);
3170 if (r_timereport_active)
3171 R_TimeReport("rtlights");
3173 // don't let sound skip if going slow
3174 if (r_refdef.extraupdate)
3177 if (cl.csqc_vidvars.drawworld)
3179 R_DrawLightningBeams();
3180 if (r_timereport_active)
3181 R_TimeReport("lightning");
3184 if (r_timereport_active)
3185 R_TimeReport("particles");
3188 if (r_timereport_active)
3189 R_TimeReport("explosions");
3192 if (gl_support_fragment_shader)
3194 qglUseProgramObjectARB(0);CHECKGLERROR
3196 VM_CL_AddPolygonsToMeshQueue();
3198 if (r_view.showdebug)
3200 if (cl_locs_show.integer)
3203 if (r_timereport_active)
3204 R_TimeReport("showlocs");
3207 if (r_drawportals.integer)
3210 if (r_timereport_active)
3211 R_TimeReport("portals");
3214 if (r_showbboxes.value > 0)
3216 R_DrawEntityBBoxes();
3217 if (r_timereport_active)
3218 R_TimeReport("bboxes");
3222 if (gl_support_fragment_shader)
3224 qglUseProgramObjectARB(0);CHECKGLERROR
3226 R_MeshQueue_RenderTransparent();
3227 if (r_timereport_active)
3228 R_TimeReport("drawtrans");
3230 if (gl_support_fragment_shader)
3232 qglUseProgramObjectARB(0);CHECKGLERROR
3235 if (cl.csqc_vidvars.drawworld)
3238 if (r_timereport_active)
3239 R_TimeReport("coronas");
3242 // don't let sound skip if going slow
3243 if (r_refdef.extraupdate)
3246 R_ResetViewRendering2D();
3249 static const int bboxelements[36] =
3259 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3262 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3263 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3264 GL_DepthMask(false);
3265 GL_DepthRange(0, 1);
3266 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3267 R_Mesh_Matrix(&identitymatrix);
3268 R_Mesh_ResetTextureState();
3270 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3271 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3272 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3273 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3274 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3275 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3276 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3277 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3278 R_FillColors(color4f, 8, cr, cg, cb, ca);
3279 if (r_refdef.fogenabled)
3281 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3283 f1 = FogPoint_World(v);
3285 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3286 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3287 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3290 R_Mesh_VertexPointer(vertex3f, 0, 0);
3291 R_Mesh_ColorPointer(color4f, 0, 0);
3292 R_Mesh_ResetTextureState();
3293 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3296 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3300 prvm_edict_t *edict;
3301 // this function draws bounding boxes of server entities
3305 for (i = 0;i < numsurfaces;i++)
3307 edict = PRVM_EDICT_NUM(surfacelist[i]);
3308 switch ((int)edict->fields.server->solid)
3310 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3311 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3312 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3313 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3314 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3315 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3317 color[3] *= r_showbboxes.value;
3318 color[3] = bound(0, color[3], 1);
3319 GL_DepthTest(!r_showdisabledepthtest.integer);
3320 GL_CullFace(r_view.cullface_front);
3321 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3326 static void R_DrawEntityBBoxes(void)
3329 prvm_edict_t *edict;
3331 // this function draws bounding boxes of server entities
3335 for (i = 0;i < prog->num_edicts;i++)
3337 edict = PRVM_EDICT_NUM(i);
3338 if (edict->priv.server->free)
3340 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3341 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3346 int nomodelelements[24] =
3358 float nomodelvertex3f[6*3] =
3368 float nomodelcolor4f[6*4] =
3370 0.0f, 0.0f, 0.5f, 1.0f,
3371 0.0f, 0.0f, 0.5f, 1.0f,
3372 0.0f, 0.5f, 0.0f, 1.0f,
3373 0.0f, 0.5f, 0.0f, 1.0f,
3374 0.5f, 0.0f, 0.0f, 1.0f,
3375 0.5f, 0.0f, 0.0f, 1.0f
3378 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3383 // this is only called once per entity so numsurfaces is always 1, and
3384 // surfacelist is always {0}, so this code does not handle batches
3385 R_Mesh_Matrix(&ent->matrix);
3387 if (ent->flags & EF_ADDITIVE)
3389 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3390 GL_DepthMask(false);
3392 else if (ent->alpha < 1)
3394 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3395 GL_DepthMask(false);
3399 GL_BlendFunc(GL_ONE, GL_ZERO);
3402 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3403 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3404 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3405 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3406 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3407 if (r_refdef.fogenabled)
3410 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3411 R_Mesh_ColorPointer(color4f, 0, 0);
3412 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3413 f1 = FogPoint_World(org);
3415 for (i = 0, c = color4f;i < 6;i++, c += 4)
3417 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3418 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3419 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3423 else if (ent->alpha != 1)
3425 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3426 R_Mesh_ColorPointer(color4f, 0, 0);
3427 for (i = 0, c = color4f;i < 6;i++, c += 4)
3431 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3432 R_Mesh_ResetTextureState();
3433 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3436 void R_DrawNoModel(entity_render_t *ent)
3439 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3440 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3441 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3443 // R_DrawNoModelCallback(ent, 0);
3446 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3448 vec3_t right1, right2, diff, normal;
3450 VectorSubtract (org2, org1, normal);
3452 // calculate 'right' vector for start
3453 VectorSubtract (r_view.origin, org1, diff);
3454 CrossProduct (normal, diff, right1);
3455 VectorNormalize (right1);
3457 // calculate 'right' vector for end
3458 VectorSubtract (r_view.origin, org2, diff);
3459 CrossProduct (normal, diff, right2);
3460 VectorNormalize (right2);
3462 vert[ 0] = org1[0] + width * right1[0];
3463 vert[ 1] = org1[1] + width * right1[1];
3464 vert[ 2] = org1[2] + width * right1[2];
3465 vert[ 3] = org1[0] - width * right1[0];
3466 vert[ 4] = org1[1] - width * right1[1];
3467 vert[ 5] = org1[2] - width * right1[2];
3468 vert[ 6] = org2[0] - width * right2[0];
3469 vert[ 7] = org2[1] - width * right2[1];
3470 vert[ 8] = org2[2] - width * right2[2];
3471 vert[ 9] = org2[0] + width * right2[0];
3472 vert[10] = org2[1] + width * right2[1];
3473 vert[11] = org2[2] + width * right2[2];
3476 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3478 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)
3483 if (r_refdef.fogenabled)
3484 fog = FogPoint_World(origin);
3486 R_Mesh_Matrix(&identitymatrix);
3487 GL_BlendFunc(blendfunc1, blendfunc2);
3493 GL_CullFace(r_view.cullface_front);
3496 GL_CullFace(r_view.cullface_back);
3498 GL_DepthMask(false);
3499 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3500 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3501 GL_DepthTest(!depthdisable);
3503 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3504 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3505 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3506 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3507 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3508 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3509 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3510 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3511 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3512 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3513 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3514 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3516 R_Mesh_VertexPointer(vertex3f, 0, 0);
3517 R_Mesh_ColorPointer(NULL, 0, 0);
3518 R_Mesh_ResetTextureState();
3519 R_Mesh_TexBind(0, R_GetTexture(texture));
3520 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3521 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3522 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3523 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3525 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3527 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3528 GL_BlendFunc(blendfunc1, GL_ONE);
3530 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);
3531 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3535 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3540 VectorSet(v, x, y, z);
3541 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3542 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3544 if (i == mesh->numvertices)
3546 if (mesh->numvertices < mesh->maxvertices)
3548 VectorCopy(v, vertex3f);
3549 mesh->numvertices++;
3551 return mesh->numvertices;
3557 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3561 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3562 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3563 e = mesh->element3i + mesh->numtriangles * 3;
3564 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3566 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3567 if (mesh->numtriangles < mesh->maxtriangles)
3572 mesh->numtriangles++;
3574 element[1] = element[2];
3578 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3582 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3583 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3584 e = mesh->element3i + mesh->numtriangles * 3;
3585 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3587 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3588 if (mesh->numtriangles < mesh->maxtriangles)
3593 mesh->numtriangles++;
3595 element[1] = element[2];
3599 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3600 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3602 int planenum, planenum2;
3605 mplane_t *plane, *plane2;
3607 double temppoints[2][256*3];
3608 // figure out how large a bounding box we need to properly compute this brush
3610 for (w = 0;w < numplanes;w++)
3611 maxdist = max(maxdist, planes[w].dist);
3612 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3613 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3614 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3618 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3619 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3621 if (planenum2 == planenum)
3623 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);
3626 if (tempnumpoints < 3)
3628 // generate elements forming a triangle fan for this polygon
3629 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3633 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3636 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3637 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3638 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3639 GL_LockArrays(0, brush->numpoints);
3640 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3641 GL_LockArrays(0, 0);
3644 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3647 if (!surface->num_collisiontriangles)
3649 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3650 i = (int)(((size_t)surface) / sizeof(msurface_t));
3651 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
3652 GL_LockArrays(0, surface->num_collisionvertices);
3653 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3654 GL_LockArrays(0, 0);
3657 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)
3659 texturelayer_t *layer;
3660 layer = t->currentlayers + t->currentnumlayers++;
3662 layer->depthmask = depthmask;
3663 layer->blendfunc1 = blendfunc1;
3664 layer->blendfunc2 = blendfunc2;
3665 layer->texture = texture;
3666 layer->texmatrix = *matrix;
3667 layer->color[0] = r * r_view.colorscale;
3668 layer->color[1] = g * r_view.colorscale;
3669 layer->color[2] = b * r_view.colorscale;
3670 layer->color[3] = a;
3673 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3676 index = parms[2] + r_refdef.time * parms[3];
3677 index -= floor(index);
3681 case Q3WAVEFUNC_NONE:
3682 case Q3WAVEFUNC_NOISE:
3683 case Q3WAVEFUNC_COUNT:
3686 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3687 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3688 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3689 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3690 case Q3WAVEFUNC_TRIANGLE:
3692 f = index - floor(index);
3703 return (float)(parms[0] + parms[1] * f);
3706 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3709 model_t *model = ent->model;
3712 q3shaderinfo_layer_tcmod_t *tcmod;
3714 // switch to an alternate material if this is a q1bsp animated material
3716 texture_t *texture = t;
3717 int s = ent->skinnum;
3718 if ((unsigned int)s >= (unsigned int)model->numskins)
3720 if (model->skinscenes)
3722 if (model->skinscenes[s].framecount > 1)
3723 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3725 s = model->skinscenes[s].firstframe;
3728 t = t + s * model->num_surfaces;
3731 // use an alternate animation if the entity's frame is not 0,
3732 // and only if the texture has an alternate animation
3733 if (ent->frame2 != 0 && t->anim_total[1])
3734 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3736 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3738 texture->currentframe = t;
3741 // update currentskinframe to be a qw skin or animation frame
3742 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3744 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3746 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3747 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3748 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);
3750 t->currentskinframe = r_qwskincache_skinframe[i];
3751 if (t->currentskinframe == NULL)
3752 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3754 else if (t->numskinframes >= 2)
3755 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3756 if (t->backgroundnumskinframes >= 2)
3757 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3759 t->currentmaterialflags = t->basematerialflags;
3760 t->currentalpha = ent->alpha;
3761 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3763 t->currentalpha *= r_wateralpha.value;
3764 // if rendering refraction/reflection, disable transparency
3765 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3766 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3768 if (!(ent->flags & RENDER_LIGHT))
3769 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3770 if (ent->effects & EF_ADDITIVE)
3771 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3772 else if (t->currentalpha < 1)
3773 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3774 if (ent->effects & EF_DOUBLESIDED)
3775 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3776 if (ent->effects & EF_NODEPTHTEST)
3777 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3778 if (ent->flags & RENDER_VIEWMODEL)
3779 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3780 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3781 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3782 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3783 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3785 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3788 switch(tcmod->tcmod)
3792 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3793 matrix = r_waterscrollmatrix;
3795 matrix = identitymatrix;
3797 case Q3TCMOD_ENTITYTRANSLATE:
3798 // this is used in Q3 to allow the gamecode to control texcoord
3799 // scrolling on the entity, which is not supported in darkplaces yet.
3800 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3802 case Q3TCMOD_ROTATE:
3803 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3804 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3805 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3808 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3810 case Q3TCMOD_SCROLL:
3811 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3813 case Q3TCMOD_STRETCH:
3814 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3815 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3817 case Q3TCMOD_TRANSFORM:
3818 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3819 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3820 VectorSet(tcmat + 6, 0 , 0 , 1);
3821 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3822 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3824 case Q3TCMOD_TURBULENT:
3825 // this is handled in the RSurf_PrepareVertices function
3826 matrix = identitymatrix;
3829 // either replace or concatenate the transformation
3831 t->currenttexmatrix = matrix;
3834 matrix4x4_t temp = t->currenttexmatrix;
3835 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3839 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3840 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3841 t->glosstexture = r_texture_black;
3842 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3843 t->backgroundglosstexture = r_texture_black;
3844 t->specularpower = r_shadow_glossexponent.value;
3845 // TODO: store reference values for these in the texture?
3846 t->specularscale = 0;
3847 if (r_shadow_gloss.integer > 0)
3849 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3851 if (r_shadow_glossintensity.value > 0)
3853 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3854 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3855 t->specularscale = r_shadow_glossintensity.value;
3858 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3860 t->glosstexture = r_texture_white;
3861 t->backgroundglosstexture = r_texture_white;
3862 t->specularscale = r_shadow_gloss2intensity.value;
3866 // lightmaps mode looks bad with dlights using actual texturing, so turn
3867 // off the colormap and glossmap, but leave the normalmap on as it still
3868 // accurately represents the shading involved
3869 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3871 t->basetexture = r_texture_white;
3872 t->specularscale = 0;
3875 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3876 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3877 // submodels are biased to avoid z-fighting with world surfaces that they
3878 // may be exactly overlapping (avoids z-fighting artifacts on certain
3879 // doors and things in Quake maps)
3880 if (ent->model->brush.submodel)
3882 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3883 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3886 VectorClear(t->dlightcolor);
3887 t->currentnumlayers = 0;
3888 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3890 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3892 int blendfunc1, blendfunc2, depthmask;
3893 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3895 blendfunc1 = GL_SRC_ALPHA;
3896 blendfunc2 = GL_ONE;
3898 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3900 blendfunc1 = GL_SRC_ALPHA;
3901 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3903 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3905 blendfunc1 = t->customblendfunc[0];
3906 blendfunc2 = t->customblendfunc[1];
3910 blendfunc1 = GL_ONE;
3911 blendfunc2 = GL_ZERO;
3913 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3914 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3916 rtexture_t *currentbasetexture;
3918 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3919 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3920 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3921 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3923 // fullbright is not affected by r_refdef.lightmapintensity
3924 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3925 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3926 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);
3927 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3928 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);
3933 // set the color tint used for lights affecting this surface
3934 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3936 // q3bsp has no lightmap updates, so the lightstylevalue that
3937 // would normally be baked into the lightmap must be
3938 // applied to the color
3939 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
3940 if (ent->model->type == mod_brushq3)
3941 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3942 colorscale *= r_refdef.lightmapintensity;
3943 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);
3944 if (r_ambient.value >= (1.0f/64.0f))
3945 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);
3946 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3948 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);
3949 if (r_ambient.value >= (1.0f/64.0f))
3950 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);
3952 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3954 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);
3955 if (r_ambient.value >= (1.0f/64.0f))
3956 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);
3959 if (t->currentskinframe->glow != NULL)
3960 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);
3961 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3963 // if this is opaque use alpha blend which will darken the earlier
3966 // if this is an alpha blended material, all the earlier passes
3967 // were darkened by fog already, so we only need to add the fog
3968 // color ontop through the fog mask texture
3970 // if this is an additive blended material, all the earlier passes
3971 // were darkened by fog already, and we should not add fog color
3972 // (because the background was not darkened, there is no fog color
3973 // that was lost behind it).
3974 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);
3981 void R_UpdateAllTextureInfo(entity_render_t *ent)
3985 for (i = 0;i < ent->model->num_texturesperskin;i++)
3986 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3989 rsurfacestate_t rsurface;
3991 void R_Mesh_ResizeArrays(int newvertices)
3994 if (rsurface.array_size >= newvertices)
3996 if (rsurface.array_modelvertex3f)
3997 Mem_Free(rsurface.array_modelvertex3f);
3998 rsurface.array_size = (newvertices + 1023) & ~1023;
3999 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4000 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4001 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4002 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4003 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4004 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4005 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4006 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4007 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4008 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4009 rsurface.array_color4f = base + rsurface.array_size * 27;
4010 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4013 void RSurf_CleanUp(void)
4016 if (rsurface.mode == RSURFMODE_GLSL)
4018 qglUseProgramObjectARB(0);CHECKGLERROR
4020 GL_AlphaTest(false);
4021 rsurface.mode = RSURFMODE_NONE;
4022 rsurface.uselightmaptexture = false;
4023 rsurface.texture = NULL;
4026 void RSurf_ActiveWorldEntity(void)
4028 model_t *model = r_refdef.worldmodel;
4030 if (rsurface.array_size < model->surfmesh.num_vertices)
4031 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4032 rsurface.matrix = identitymatrix;
4033 rsurface.inversematrix = identitymatrix;
4034 R_Mesh_Matrix(&identitymatrix);
4035 VectorCopy(r_view.origin, rsurface.modelorg);
4036 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4037 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4038 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4039 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4040 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4041 rsurface.frameblend[0].frame = 0;
4042 rsurface.frameblend[0].lerp = 1;
4043 rsurface.frameblend[1].frame = 0;
4044 rsurface.frameblend[1].lerp = 0;
4045 rsurface.frameblend[2].frame = 0;
4046 rsurface.frameblend[2].lerp = 0;
4047 rsurface.frameblend[3].frame = 0;
4048 rsurface.frameblend[3].lerp = 0;
4049 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4050 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4051 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4052 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4053 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4054 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4055 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4056 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4057 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4058 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4059 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4060 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4061 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4062 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4063 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4064 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4065 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4066 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4067 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4068 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4069 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4070 rsurface.modelelement3i = model->surfmesh.data_element3i;
4071 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4072 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4073 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4074 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4075 rsurface.modelsurfaces = model->data_surfaces;
4076 rsurface.generatedvertex = false;
4077 rsurface.vertex3f = rsurface.modelvertex3f;
4078 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4079 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4080 rsurface.svector3f = rsurface.modelsvector3f;
4081 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4082 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4083 rsurface.tvector3f = rsurface.modeltvector3f;
4084 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4085 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4086 rsurface.normal3f = rsurface.modelnormal3f;
4087 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4088 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4089 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4092 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4094 model_t *model = ent->model;
4096 if (rsurface.array_size < model->surfmesh.num_vertices)
4097 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4098 rsurface.matrix = ent->matrix;
4099 rsurface.inversematrix = ent->inversematrix;
4100 R_Mesh_Matrix(&rsurface.matrix);
4101 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4102 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4103 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4104 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4105 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4106 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4107 rsurface.frameblend[0] = ent->frameblend[0];
4108 rsurface.frameblend[1] = ent->frameblend[1];
4109 rsurface.frameblend[2] = ent->frameblend[2];
4110 rsurface.frameblend[3] = ent->frameblend[3];
4111 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4115 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4116 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4117 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4118 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4119 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4121 else if (wantnormals)
4123 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4124 rsurface.modelsvector3f = NULL;
4125 rsurface.modeltvector3f = NULL;
4126 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4127 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4131 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4132 rsurface.modelsvector3f = NULL;
4133 rsurface.modeltvector3f = NULL;
4134 rsurface.modelnormal3f = NULL;
4135 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4137 rsurface.modelvertex3f_bufferobject = 0;
4138 rsurface.modelvertex3f_bufferoffset = 0;
4139 rsurface.modelsvector3f_bufferobject = 0;
4140 rsurface.modelsvector3f_bufferoffset = 0;
4141 rsurface.modeltvector3f_bufferobject = 0;
4142 rsurface.modeltvector3f_bufferoffset = 0;
4143 rsurface.modelnormal3f_bufferobject = 0;
4144 rsurface.modelnormal3f_bufferoffset = 0;
4145 rsurface.generatedvertex = true;
4149 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4150 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4151 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4152 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4153 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4154 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4155 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4156 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4157 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4158 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4159 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4160 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4161 rsurface.generatedvertex = false;
4163 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4164 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4165 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4166 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4167 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4168 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4169 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4170 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4171 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4172 rsurface.modelelement3i = model->surfmesh.data_element3i;
4173 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4174 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4175 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4176 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4177 rsurface.modelsurfaces = model->data_surfaces;
4178 rsurface.vertex3f = rsurface.modelvertex3f;
4179 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4180 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4181 rsurface.svector3f = rsurface.modelsvector3f;
4182 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4183 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4184 rsurface.tvector3f = rsurface.modeltvector3f;
4185 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4186 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4187 rsurface.normal3f = rsurface.modelnormal3f;
4188 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4189 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4190 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4193 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4194 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4197 int texturesurfaceindex;
4202 const float *v1, *in_tc;
4204 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4206 q3shaderinfo_deform_t *deform;
4207 // 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
4208 if (rsurface.generatedvertex)
4210 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4211 generatenormals = true;
4212 for (i = 0;i < Q3MAXDEFORMS;i++)
4214 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4216 generatetangents = true;
4217 generatenormals = true;
4219 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4220 generatenormals = true;
4222 if (generatenormals && !rsurface.modelnormal3f)
4224 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4225 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4226 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4227 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4229 if (generatetangents && !rsurface.modelsvector3f)
4231 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4232 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4233 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4234 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4235 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4236 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4237 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);
4240 rsurface.vertex3f = rsurface.modelvertex3f;
4241 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4242 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4243 rsurface.svector3f = rsurface.modelsvector3f;
4244 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4245 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4246 rsurface.tvector3f = rsurface.modeltvector3f;
4247 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4248 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4249 rsurface.normal3f = rsurface.modelnormal3f;
4250 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4251 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4252 // if vertices are deformed (sprite flares and things in maps, possibly
4253 // water waves, bulges and other deformations), generate them into
4254 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4255 // (may be static model data or generated data for an animated model, or
4256 // the previous deform pass)
4257 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4259 switch (deform->deform)
4262 case Q3DEFORM_PROJECTIONSHADOW:
4263 case Q3DEFORM_TEXT0:
4264 case Q3DEFORM_TEXT1:
4265 case Q3DEFORM_TEXT2:
4266 case Q3DEFORM_TEXT3:
4267 case Q3DEFORM_TEXT4:
4268 case Q3DEFORM_TEXT5:
4269 case Q3DEFORM_TEXT6:
4270 case Q3DEFORM_TEXT7:
4273 case Q3DEFORM_AUTOSPRITE:
4274 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4275 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4276 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4277 VectorNormalize(newforward);
4278 VectorNormalize(newright);
4279 VectorNormalize(newup);
4280 // make deformed versions of only the model vertices used by the specified surfaces
4281 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4283 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4284 // a single autosprite surface can contain multiple sprites...
4285 for (j = 0;j < surface->num_vertices - 3;j += 4)
4287 VectorClear(center);
4288 for (i = 0;i < 4;i++)
4289 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4290 VectorScale(center, 0.25f, center);
4291 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4292 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4293 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4294 for (i = 0;i < 4;i++)
4296 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4297 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4300 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);
4301 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);
4303 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4304 rsurface.vertex3f_bufferobject = 0;
4305 rsurface.vertex3f_bufferoffset = 0;
4306 rsurface.svector3f = rsurface.array_deformedsvector3f;
4307 rsurface.svector3f_bufferobject = 0;
4308 rsurface.svector3f_bufferoffset = 0;
4309 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4310 rsurface.tvector3f_bufferobject = 0;
4311 rsurface.tvector3f_bufferoffset = 0;
4312 rsurface.normal3f = rsurface.array_deformednormal3f;
4313 rsurface.normal3f_bufferobject = 0;
4314 rsurface.normal3f_bufferoffset = 0;
4316 case Q3DEFORM_AUTOSPRITE2:
4317 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4318 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4319 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4320 VectorNormalize(newforward);
4321 VectorNormalize(newright);
4322 VectorNormalize(newup);
4323 // make deformed versions of only the model vertices used by the specified surfaces
4324 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4326 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4327 const float *v1, *v2;
4337 memset(shortest, 0, sizeof(shortest));
4338 // a single autosprite surface can contain multiple sprites...
4339 for (j = 0;j < surface->num_vertices - 3;j += 4)
4341 VectorClear(center);
4342 for (i = 0;i < 4;i++)
4343 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4344 VectorScale(center, 0.25f, center);
4345 // find the two shortest edges, then use them to define the
4346 // axis vectors for rotating around the central axis
4347 for (i = 0;i < 6;i++)
4349 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4350 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4352 Debug_PolygonBegin(NULL, 0, false, 0);
4353 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4354 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);
4355 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4358 l = VectorDistance2(v1, v2);
4359 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4361 l += (1.0f / 1024.0f);
4362 if (shortest[0].length2 > l || i == 0)
4364 shortest[1] = shortest[0];
4365 shortest[0].length2 = l;
4366 shortest[0].v1 = v1;
4367 shortest[0].v2 = v2;
4369 else if (shortest[1].length2 > l || i == 1)
4371 shortest[1].length2 = l;
4372 shortest[1].v1 = v1;
4373 shortest[1].v2 = v2;
4376 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4377 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4379 Debug_PolygonBegin(NULL, 0, false, 0);
4380 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4381 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);
4382 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4385 // this calculates the right vector from the shortest edge
4386 // and the up vector from the edge midpoints
4387 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4388 VectorNormalize(right);
4389 VectorSubtract(end, start, up);
4390 VectorNormalize(up);
4391 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4392 //VectorSubtract(rsurface.modelorg, center, forward);
4393 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4394 VectorNegate(forward, forward);
4395 VectorReflect(forward, 0, up, forward);
4396 VectorNormalize(forward);
4397 CrossProduct(up, forward, newright);
4398 VectorNormalize(newright);
4400 Debug_PolygonBegin(NULL, 0, false, 0);
4401 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);
4402 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4403 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4407 Debug_PolygonBegin(NULL, 0, false, 0);
4408 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4409 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4410 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4413 // rotate the quad around the up axis vector, this is made
4414 // especially easy by the fact we know the quad is flat,
4415 // so we only have to subtract the center position and
4416 // measure distance along the right vector, and then
4417 // multiply that by the newright vector and add back the
4419 // we also need to subtract the old position to undo the
4420 // displacement from the center, which we do with a
4421 // DotProduct, the subtraction/addition of center is also
4422 // optimized into DotProducts here
4423 l = DotProduct(right, center);
4424 for (i = 0;i < 4;i++)
4426 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4427 f = DotProduct(right, v1) - l;
4428 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4431 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);
4432 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);
4434 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4435 rsurface.vertex3f_bufferobject = 0;
4436 rsurface.vertex3f_bufferoffset = 0;
4437 rsurface.svector3f = rsurface.array_deformedsvector3f;
4438 rsurface.svector3f_bufferobject = 0;
4439 rsurface.svector3f_bufferoffset = 0;
4440 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4441 rsurface.tvector3f_bufferobject = 0;
4442 rsurface.tvector3f_bufferoffset = 0;
4443 rsurface.normal3f = rsurface.array_deformednormal3f;
4444 rsurface.normal3f_bufferobject = 0;
4445 rsurface.normal3f_bufferoffset = 0;
4447 case Q3DEFORM_NORMAL:
4448 // deform the normals to make reflections wavey
4449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4452 for (j = 0;j < surface->num_vertices;j++)
4455 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4456 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4457 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4458 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4459 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4460 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4461 VectorNormalize(normal);
4463 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);
4465 rsurface.svector3f = rsurface.array_deformedsvector3f;
4466 rsurface.svector3f_bufferobject = 0;
4467 rsurface.svector3f_bufferoffset = 0;
4468 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4469 rsurface.tvector3f_bufferobject = 0;
4470 rsurface.tvector3f_bufferoffset = 0;
4471 rsurface.normal3f = rsurface.array_deformednormal3f;
4472 rsurface.normal3f_bufferobject = 0;
4473 rsurface.normal3f_bufferoffset = 0;
4476 // deform vertex array to make wavey water and flags and such
4477 waveparms[0] = deform->waveparms[0];
4478 waveparms[1] = deform->waveparms[1];
4479 waveparms[2] = deform->waveparms[2];
4480 waveparms[3] = deform->waveparms[3];
4481 // this is how a divisor of vertex influence on deformation
4482 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4483 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4484 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4487 for (j = 0;j < surface->num_vertices;j++)
4489 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4490 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4491 // if the wavefunc depends on time, evaluate it per-vertex
4494 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4495 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4497 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4500 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4501 rsurface.vertex3f_bufferobject = 0;
4502 rsurface.vertex3f_bufferoffset = 0;
4504 case Q3DEFORM_BULGE:
4505 // deform vertex array to make the surface have moving bulges
4506 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4508 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4509 for (j = 0;j < surface->num_vertices;j++)
4511 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4512 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4515 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4516 rsurface.vertex3f_bufferobject = 0;
4517 rsurface.vertex3f_bufferoffset = 0;
4520 // deform vertex array
4521 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4522 VectorScale(deform->parms, scale, waveparms);
4523 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4525 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4526 for (j = 0;j < surface->num_vertices;j++)
4527 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4529 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4530 rsurface.vertex3f_bufferobject = 0;
4531 rsurface.vertex3f_bufferoffset = 0;
4535 // generate texcoords based on the chosen texcoord source
4536 switch(rsurface.texture->tcgen.tcgen)
4539 case Q3TCGEN_TEXTURE:
4540 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4541 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4542 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4544 case Q3TCGEN_LIGHTMAP:
4545 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4546 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4547 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4549 case Q3TCGEN_VECTOR:
4550 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4552 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4553 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)
4555 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4556 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4559 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4560 rsurface.texcoordtexture2f_bufferobject = 0;
4561 rsurface.texcoordtexture2f_bufferoffset = 0;
4563 case Q3TCGEN_ENVIRONMENT:
4564 // make environment reflections using a spheremap
4565 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4567 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4568 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4569 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4570 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4571 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4573 float l, d, eyedir[3];
4574 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4575 l = 0.5f / VectorLength(eyedir);
4576 d = DotProduct(normal, eyedir)*2;
4577 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4578 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4581 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4582 rsurface.texcoordtexture2f_bufferobject = 0;
4583 rsurface.texcoordtexture2f_bufferoffset = 0;
4586 // the only tcmod that needs software vertex processing is turbulent, so
4587 // check for it here and apply the changes if needed
4588 // and we only support that as the first one
4589 // (handling a mixture of turbulent and other tcmods would be problematic
4590 // without punting it entirely to a software path)
4591 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4593 amplitude = rsurface.texture->tcmods[0].parms[1];
4594 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4595 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4597 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4598 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)
4600 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4601 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4604 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4605 rsurface.texcoordtexture2f_bufferobject = 0;
4606 rsurface.texcoordtexture2f_bufferoffset = 0;
4608 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4609 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4610 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4611 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4614 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4617 const msurface_t *surface = texturesurfacelist[0];
4618 const msurface_t *surface2;
4623 // TODO: lock all array ranges before render, rather than on each surface
4624 if (texturenumsurfaces == 1)
4626 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4627 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));
4629 else if (r_batchmode.integer == 2)
4631 #define MAXBATCHTRIANGLES 4096
4632 int batchtriangles = 0;
4633 int batchelements[MAXBATCHTRIANGLES*3];
4634 for (i = 0;i < texturenumsurfaces;i = j)
4636 surface = texturesurfacelist[i];
4638 if (surface->num_triangles > MAXBATCHTRIANGLES)
4640 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));
4643 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4644 batchtriangles = surface->num_triangles;
4645 firstvertex = surface->num_firstvertex;
4646 endvertex = surface->num_firstvertex + surface->num_vertices;
4647 for (;j < texturenumsurfaces;j++)
4649 surface2 = texturesurfacelist[j];
4650 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4652 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4653 batchtriangles += surface2->num_triangles;
4654 firstvertex = min(firstvertex, surface2->num_firstvertex);
4655 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4657 surface2 = texturesurfacelist[j-1];
4658 numvertices = endvertex - firstvertex;
4659 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4662 else if (r_batchmode.integer == 1)
4664 for (i = 0;i < texturenumsurfaces;i = j)
4666 surface = texturesurfacelist[i];
4667 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4668 if (texturesurfacelist[j] != surface2)
4670 surface2 = texturesurfacelist[j-1];
4671 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4672 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4673 GL_LockArrays(surface->num_firstvertex, numvertices);
4674 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4679 for (i = 0;i < texturenumsurfaces;i++)
4681 surface = texturesurfacelist[i];
4682 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4683 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));
4688 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4690 int i, planeindex, vertexindex;
4694 r_waterstate_waterplane_t *p, *bestp;
4695 msurface_t *surface;
4696 if (r_waterstate.renderingscene)
4698 for (i = 0;i < texturenumsurfaces;i++)
4700 surface = texturesurfacelist[i];
4701 if (lightmaptexunit >= 0)
4702 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4703 if (deluxemaptexunit >= 0)
4704 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4705 // pick the closest matching water plane
4708 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4711 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4713 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4714 d += fabs(PlaneDiff(vert, &p->plane));
4716 if (bestd > d || !bestp)
4724 if (refractiontexunit >= 0)
4725 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4726 if (reflectiontexunit >= 0)
4727 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4731 if (refractiontexunit >= 0)
4732 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4733 if (reflectiontexunit >= 0)
4734 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4736 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4737 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));
4741 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4745 const msurface_t *surface = texturesurfacelist[0];
4746 const msurface_t *surface2;
4751 // TODO: lock all array ranges before render, rather than on each surface
4752 if (texturenumsurfaces == 1)
4754 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4755 if (deluxemaptexunit >= 0)
4756 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4757 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4758 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4760 else if (r_batchmode.integer == 2)
4762 #define MAXBATCHTRIANGLES 4096
4763 int batchtriangles = 0;
4764 int batchelements[MAXBATCHTRIANGLES*3];
4765 for (i = 0;i < texturenumsurfaces;i = j)
4767 surface = texturesurfacelist[i];
4768 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4769 if (deluxemaptexunit >= 0)
4770 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4772 if (surface->num_triangles > MAXBATCHTRIANGLES)
4774 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));
4777 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4778 batchtriangles = surface->num_triangles;
4779 firstvertex = surface->num_firstvertex;
4780 endvertex = surface->num_firstvertex + surface->num_vertices;
4781 for (;j < texturenumsurfaces;j++)
4783 surface2 = texturesurfacelist[j];
4784 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4786 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4787 batchtriangles += surface2->num_triangles;
4788 firstvertex = min(firstvertex, surface2->num_firstvertex);
4789 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4791 surface2 = texturesurfacelist[j-1];
4792 numvertices = endvertex - firstvertex;
4793 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4796 else if (r_batchmode.integer == 1)
4799 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4800 for (i = 0;i < texturenumsurfaces;i = j)
4802 surface = texturesurfacelist[i];
4803 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4804 if (texturesurfacelist[j] != surface2)
4806 Con_Printf(" %i", j - i);
4809 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4811 for (i = 0;i < texturenumsurfaces;i = j)
4813 surface = texturesurfacelist[i];
4814 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4815 if (deluxemaptexunit >= 0)
4816 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4817 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4818 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4821 Con_Printf(" %i", j - i);
4823 surface2 = texturesurfacelist[j-1];
4824 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4825 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4826 GL_LockArrays(surface->num_firstvertex, numvertices);
4827 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4835 for (i = 0;i < texturenumsurfaces;i++)
4837 surface = texturesurfacelist[i];
4838 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4839 if (deluxemaptexunit >= 0)
4840 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4841 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4842 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));
4847 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4850 int texturesurfaceindex;
4851 if (r_showsurfaces.integer == 2)
4853 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4855 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4856 for (j = 0;j < surface->num_triangles;j++)
4858 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4859 GL_Color(f, f, f, 1);
4860 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)));
4866 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4868 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4869 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4870 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);
4871 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4872 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));
4877 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4879 int texturesurfaceindex;
4883 if (rsurface.lightmapcolor4f)
4885 // generate color arrays for the surfaces in this list
4886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4888 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4889 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)
4891 f = FogPoint_Model(v);
4901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4903 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4904 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)
4906 f = FogPoint_Model(v);
4914 rsurface.lightmapcolor4f = rsurface.array_color4f;
4915 rsurface.lightmapcolor4f_bufferobject = 0;
4916 rsurface.lightmapcolor4f_bufferoffset = 0;
4919 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4921 int texturesurfaceindex;
4924 if (!rsurface.lightmapcolor4f)
4926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4928 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4929 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)
4937 rsurface.lightmapcolor4f = rsurface.array_color4f;
4938 rsurface.lightmapcolor4f_bufferobject = 0;
4939 rsurface.lightmapcolor4f_bufferoffset = 0;
4942 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4945 rsurface.lightmapcolor4f = NULL;
4946 rsurface.lightmapcolor4f_bufferobject = 0;
4947 rsurface.lightmapcolor4f_bufferoffset = 0;
4948 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4949 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4950 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4951 GL_Color(r, g, b, a);
4952 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4955 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4957 // TODO: optimize applyfog && applycolor case
4958 // just apply fog if necessary, and tint the fog color array if necessary
4959 rsurface.lightmapcolor4f = NULL;
4960 rsurface.lightmapcolor4f_bufferobject = 0;
4961 rsurface.lightmapcolor4f_bufferoffset = 0;
4962 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4963 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4964 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4965 GL_Color(r, g, b, a);
4966 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4969 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4971 int texturesurfaceindex;
4975 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4977 // generate color arrays for the surfaces in this list
4978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4980 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4981 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4983 if (surface->lightmapinfo->samples)
4985 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4986 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4987 VectorScale(lm, scale, c);
4988 if (surface->lightmapinfo->styles[1] != 255)
4990 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4992 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4993 VectorMA(c, scale, lm, c);
4994 if (surface->lightmapinfo->styles[2] != 255)
4997 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4998 VectorMA(c, scale, lm, c);
4999 if (surface->lightmapinfo->styles[3] != 255)
5002 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5003 VectorMA(c, scale, lm, c);
5013 rsurface.lightmapcolor4f = rsurface.array_color4f;
5014 rsurface.lightmapcolor4f_bufferobject = 0;
5015 rsurface.lightmapcolor4f_bufferoffset = 0;
5019 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5020 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5021 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5023 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5024 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5025 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5026 GL_Color(r, g, b, a);
5027 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5030 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5032 int texturesurfaceindex;
5036 vec3_t ambientcolor;
5037 vec3_t diffusecolor;
5041 VectorCopy(rsurface.modellight_lightdir, lightdir);
5042 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5043 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5044 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5045 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5046 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5047 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5048 if (VectorLength2(diffusecolor) > 0)
5050 // generate color arrays for the surfaces in this list
5051 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5053 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5054 int numverts = surface->num_vertices;
5055 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5056 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5057 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5058 // q3-style directional shading
5059 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5061 if ((f = DotProduct(c2, lightdir)) > 0)
5062 VectorMA(ambientcolor, f, diffusecolor, c);
5064 VectorCopy(ambientcolor, c);
5073 rsurface.lightmapcolor4f = rsurface.array_color4f;
5074 rsurface.lightmapcolor4f_bufferobject = 0;
5075 rsurface.lightmapcolor4f_bufferoffset = 0;
5079 r = ambientcolor[0];
5080 g = ambientcolor[1];
5081 b = ambientcolor[2];
5082 rsurface.lightmapcolor4f = NULL;
5083 rsurface.lightmapcolor4f_bufferobject = 0;
5084 rsurface.lightmapcolor4f_bufferoffset = 0;
5086 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5087 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5088 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5089 GL_Color(r, g, b, a);
5090 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5093 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5095 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5096 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5097 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5098 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5099 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5101 rsurface.mode = RSURFMODE_SHOWSURFACES;
5103 GL_BlendFunc(GL_ONE, GL_ZERO);
5104 R_Mesh_ColorPointer(NULL, 0, 0);
5105 R_Mesh_ResetTextureState();
5107 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5108 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5111 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5113 // transparent sky would be ridiculous
5114 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5116 if (rsurface.mode != RSURFMODE_SKY)
5118 if (rsurface.mode == RSURFMODE_GLSL)
5120 qglUseProgramObjectARB(0);CHECKGLERROR
5122 rsurface.mode = RSURFMODE_SKY;
5126 skyrendernow = false;
5128 // restore entity matrix
5129 R_Mesh_Matrix(&rsurface.matrix);
5131 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5132 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5133 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5134 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5136 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5137 // skymasking on them, and Quake3 never did sky masking (unlike
5138 // software Quake and software Quake2), so disable the sky masking
5139 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5140 // and skymasking also looks very bad when noclipping outside the
5141 // level, so don't use it then either.
5142 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5144 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5145 R_Mesh_ColorPointer(NULL, 0, 0);
5146 R_Mesh_ResetTextureState();
5147 if (skyrendermasked)
5149 // depth-only (masking)
5150 GL_ColorMask(0,0,0,0);
5151 // just to make sure that braindead drivers don't draw
5152 // anything despite that colormask...
5153 GL_BlendFunc(GL_ZERO, GL_ONE);
5158 GL_BlendFunc(GL_ONE, GL_ZERO);
5160 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5161 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5162 if (skyrendermasked)
5163 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5167 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5169 if (rsurface.mode != RSURFMODE_GLSL)
5171 rsurface.mode = RSURFMODE_GLSL;
5172 R_Mesh_ResetTextureState();
5175 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5176 if (!r_glsl_permutation)
5179 if (rsurface.lightmode == 2)
5180 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5182 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5183 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5184 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5185 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5186 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5187 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5189 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]);
5190 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5192 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5193 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5194 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5195 R_Mesh_ColorPointer(NULL, 0, 0);
5197 else if (rsurface.uselightmaptexture)
5199 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5200 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5201 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5202 R_Mesh_ColorPointer(NULL, 0, 0);
5206 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5207 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5208 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5209 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5212 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5215 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5216 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5217 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5219 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5223 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5224 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5225 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5226 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5228 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5230 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5235 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5237 // OpenGL 1.3 path - anything not completely ancient
5238 int texturesurfaceindex;
5239 qboolean applycolor;
5243 const texturelayer_t *layer;
5244 if (rsurface.mode != RSURFMODE_MULTIPASS)
5245 rsurface.mode = RSURFMODE_MULTIPASS;
5246 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5247 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5250 int layertexrgbscale;
5251 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5253 if (layerindex == 0)
5257 GL_AlphaTest(false);
5258 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5261 GL_DepthMask(layer->depthmask);
5262 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5263 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5265 layertexrgbscale = 4;
5266 VectorScale(layer->color, 0.25f, layercolor);
5268 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5270 layertexrgbscale = 2;
5271 VectorScale(layer->color, 0.5f, layercolor);
5275 layertexrgbscale = 1;
5276 VectorScale(layer->color, 1.0f, layercolor);
5278 layercolor[3] = layer->color[3];
5279 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5280 R_Mesh_ColorPointer(NULL, 0, 0);
5281 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5282 switch (layer->type)
5284 case TEXTURELAYERTYPE_LITTEXTURE:
5285 memset(&m, 0, sizeof(m));
5286 m.tex[0] = R_GetTexture(r_texture_white);
5287 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5288 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5289 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5290 m.tex[1] = R_GetTexture(layer->texture);
5291 m.texmatrix[1] = layer->texmatrix;
5292 m.texrgbscale[1] = layertexrgbscale;
5293 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5294 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5295 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5296 R_Mesh_TextureState(&m);
5297 if (rsurface.lightmode == 2)
5298 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5299 else if (rsurface.uselightmaptexture)
5300 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5302 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5304 case TEXTURELAYERTYPE_TEXTURE:
5305 memset(&m, 0, sizeof(m));
5306 m.tex[0] = R_GetTexture(layer->texture);
5307 m.texmatrix[0] = layer->texmatrix;
5308 m.texrgbscale[0] = layertexrgbscale;
5309 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5310 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5311 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5312 R_Mesh_TextureState(&m);
5313 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5315 case TEXTURELAYERTYPE_FOG:
5316 memset(&m, 0, sizeof(m));
5317 m.texrgbscale[0] = layertexrgbscale;
5320 m.tex[0] = R_GetTexture(layer->texture);
5321 m.texmatrix[0] = layer->texmatrix;
5322 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5323 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5324 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5326 R_Mesh_TextureState(&m);
5327 // generate a color array for the fog pass
5328 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5329 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5333 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5334 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)
5336 f = 1 - FogPoint_Model(v);
5337 c[0] = layercolor[0];
5338 c[1] = layercolor[1];
5339 c[2] = layercolor[2];
5340 c[3] = f * layercolor[3];
5343 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5346 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5348 GL_LockArrays(0, 0);
5351 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5353 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5354 GL_AlphaTest(false);
5358 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5360 // OpenGL 1.1 - crusty old voodoo path
5361 int texturesurfaceindex;
5365 const texturelayer_t *layer;
5366 if (rsurface.mode != RSURFMODE_MULTIPASS)
5367 rsurface.mode = RSURFMODE_MULTIPASS;
5368 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5369 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5373 if (layerindex == 0)
5377 GL_AlphaTest(false);
5378 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5381 GL_DepthMask(layer->depthmask);
5382 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5383 R_Mesh_ColorPointer(NULL, 0, 0);
5384 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5385 switch (layer->type)
5387 case TEXTURELAYERTYPE_LITTEXTURE:
5388 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5390 // two-pass lit texture with 2x rgbscale
5391 // first the lightmap pass
5392 memset(&m, 0, sizeof(m));
5393 m.tex[0] = R_GetTexture(r_texture_white);
5394 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5395 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5396 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5397 R_Mesh_TextureState(&m);
5398 if (rsurface.lightmode == 2)
5399 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5400 else if (rsurface.uselightmaptexture)
5401 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5403 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5404 GL_LockArrays(0, 0);
5405 // then apply the texture to it
5406 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5407 memset(&m, 0, sizeof(m));
5408 m.tex[0] = R_GetTexture(layer->texture);
5409 m.texmatrix[0] = layer->texmatrix;
5410 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5411 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5412 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5413 R_Mesh_TextureState(&m);
5414 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);
5418 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5419 memset(&m, 0, sizeof(m));
5420 m.tex[0] = R_GetTexture(layer->texture);
5421 m.texmatrix[0] = layer->texmatrix;
5422 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5423 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5424 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5425 R_Mesh_TextureState(&m);
5426 if (rsurface.lightmode == 2)
5427 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);
5429 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);
5432 case TEXTURELAYERTYPE_TEXTURE:
5433 // singletexture unlit texture with transparency support
5434 memset(&m, 0, sizeof(m));
5435 m.tex[0] = R_GetTexture(layer->texture);
5436 m.texmatrix[0] = layer->texmatrix;
5437 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5438 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5439 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5440 R_Mesh_TextureState(&m);
5441 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);
5443 case TEXTURELAYERTYPE_FOG:
5444 // singletexture fogging
5445 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5448 memset(&m, 0, sizeof(m));
5449 m.tex[0] = R_GetTexture(layer->texture);
5450 m.texmatrix[0] = layer->texmatrix;
5451 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5452 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5453 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5454 R_Mesh_TextureState(&m);
5457 R_Mesh_ResetTextureState();
5458 // generate a color array for the fog pass
5459 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5463 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5464 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)
5466 f = 1 - FogPoint_Model(v);
5467 c[0] = layer->color[0];
5468 c[1] = layer->color[1];
5469 c[2] = layer->color[2];
5470 c[3] = f * layer->color[3];
5473 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5476 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5478 GL_LockArrays(0, 0);
5481 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5483 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5484 GL_AlphaTest(false);
5488 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5490 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5492 rsurface.rtlight = NULL;
5496 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5498 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5500 if (rsurface.mode != RSURFMODE_MULTIPASS)
5501 rsurface.mode = RSURFMODE_MULTIPASS;
5502 if (r_depthfirst.integer == 3)
5504 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5505 if (!r_view.showdebug)
5506 GL_Color(0, 0, 0, 1);
5508 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5512 GL_ColorMask(0,0,0,0);
5515 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5516 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5517 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5519 GL_BlendFunc(GL_ONE, GL_ZERO);
5521 GL_AlphaTest(false);
5522 R_Mesh_ColorPointer(NULL, 0, 0);
5523 R_Mesh_ResetTextureState();
5524 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5525 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5526 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5527 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5529 else if (r_depthfirst.integer == 3)
5531 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5533 GL_Color(0, 0, 0, 1);
5534 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5536 else if (r_showsurfaces.integer)
5538 if (rsurface.mode != RSURFMODE_MULTIPASS)
5539 rsurface.mode = RSURFMODE_MULTIPASS;
5540 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5541 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5543 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5544 GL_BlendFunc(GL_ONE, GL_ZERO);
5545 GL_DepthMask(writedepth);
5547 GL_AlphaTest(false);
5548 R_Mesh_ColorPointer(NULL, 0, 0);
5549 R_Mesh_ResetTextureState();
5550 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5551 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5552 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5554 else if (gl_lightmaps.integer)
5557 if (rsurface.mode != RSURFMODE_MULTIPASS)
5558 rsurface.mode = RSURFMODE_MULTIPASS;
5559 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5561 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5562 GL_BlendFunc(GL_ONE, GL_ZERO);
5563 GL_DepthMask(writedepth);
5565 GL_AlphaTest(false);
5566 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5567 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5568 R_Mesh_ColorPointer(NULL, 0, 0);
5569 memset(&m, 0, sizeof(m));
5570 m.tex[0] = R_GetTexture(r_texture_white);
5571 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5572 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5573 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5574 R_Mesh_TextureState(&m);
5575 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5576 if (rsurface.lightmode == 2)
5577 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5578 else if (rsurface.uselightmaptexture)
5579 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5581 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5582 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5584 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5586 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5587 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5589 else if (rsurface.texture->currentnumlayers)
5591 // write depth for anything we skipped on the depth-only pass earlier
5592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5594 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5595 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5596 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5597 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5598 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5599 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5600 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5601 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5602 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5603 if (r_glsl.integer && gl_support_fragment_shader)
5604 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5605 else if (gl_combine.integer && r_textureunits.integer >= 2)
5606 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5608 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5609 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5612 GL_LockArrays(0, 0);
5615 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5618 int texturenumsurfaces, endsurface;
5620 msurface_t *surface;
5621 msurface_t *texturesurfacelist[1024];
5623 // if the model is static it doesn't matter what value we give for
5624 // wantnormals and wanttangents, so this logic uses only rules applicable
5625 // to a model, knowing that they are meaningless otherwise
5626 if (ent == r_refdef.worldentity)
5627 RSurf_ActiveWorldEntity();
5628 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5629 RSurf_ActiveModelEntity(ent, false, false);
5631 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5633 for (i = 0;i < numsurfaces;i = j)
5636 surface = rsurface.modelsurfaces + surfacelist[i];
5637 texture = surface->texture;
5638 R_UpdateTextureInfo(ent, texture);
5639 rsurface.texture = texture->currentframe;
5640 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5641 // scan ahead until we find a different texture
5642 endsurface = min(i + 1024, numsurfaces);
5643 texturenumsurfaces = 0;
5644 texturesurfacelist[texturenumsurfaces++] = surface;
5645 for (;j < endsurface;j++)
5647 surface = rsurface.modelsurfaces + surfacelist[j];
5648 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5650 texturesurfacelist[texturenumsurfaces++] = surface;
5652 // render the range of surfaces
5653 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5659 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5662 vec3_t tempcenter, center;
5664 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5667 for (i = 0;i < numsurfaces;i++)
5668 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5669 R_Water_AddWaterPlane(surfacelist[i]);
5672 // break the surface list down into batches by texture and use of lightmapping
5673 for (i = 0;i < numsurfaces;i = j)
5676 // texture is the base texture pointer, rsurface.texture is the
5677 // current frame/skin the texture is directing us to use (for example
5678 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5679 // use skin 1 instead)
5680 texture = surfacelist[i]->texture;
5681 rsurface.texture = texture->currentframe;
5682 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5683 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5685 // if this texture is not the kind we want, skip ahead to the next one
5686 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5690 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5692 // transparent surfaces get pushed off into the transparent queue
5693 const msurface_t *surface = surfacelist[i];
5696 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5697 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5698 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5699 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5700 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5704 // simply scan ahead until we find a different texture or lightmap state
5705 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5707 // render the range of surfaces
5708 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5713 float locboxvertex3f[6*4*3] =
5715 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5716 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5717 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5718 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5719 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5720 1,0,0, 0,0,0, 0,1,0, 1,1,0
5723 int locboxelement3i[6*2*3] =
5733 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5736 cl_locnode_t *loc = (cl_locnode_t *)ent;
5738 float vertex3f[6*4*3];
5740 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5741 GL_DepthMask(false);
5742 GL_DepthRange(0, 1);
5743 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5745 GL_CullFace(GL_NONE);
5746 R_Mesh_Matrix(&identitymatrix);
5748 R_Mesh_VertexPointer(vertex3f, 0, 0);
5749 R_Mesh_ColorPointer(NULL, 0, 0);
5750 R_Mesh_ResetTextureState();
5753 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5754 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5755 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5756 surfacelist[0] < 0 ? 0.5f : 0.125f);
5758 if (VectorCompare(loc->mins, loc->maxs))
5760 VectorSet(size, 2, 2, 2);
5761 VectorMA(loc->mins, -0.5f, size, mins);
5765 VectorCopy(loc->mins, mins);
5766 VectorSubtract(loc->maxs, loc->mins, size);
5769 for (i = 0;i < 6*4*3;)
5770 for (j = 0;j < 3;j++, i++)
5771 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5773 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5776 void R_DrawLocs(void)
5779 cl_locnode_t *loc, *nearestloc;
5781 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5782 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5784 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5785 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5789 void R_DrawCollisionBrushes(entity_render_t *ent)
5793 msurface_t *surface;
5794 model_t *model = ent->model;
5795 if (!model->brush.num_brushes)
5798 R_Mesh_ColorPointer(NULL, 0, 0);
5799 R_Mesh_ResetTextureState();
5800 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5801 GL_DepthMask(false);
5802 GL_DepthRange(0, 1);
5803 GL_DepthTest(!r_showdisabledepthtest.integer);
5804 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5805 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5806 if (brush->colbrushf && brush->colbrushf->numtriangles)
5807 R_DrawCollisionBrush(brush->colbrushf);
5808 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5809 if (surface->num_collisiontriangles)
5810 R_DrawCollisionSurface(ent, surface);
5811 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5814 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5817 const int *elements;
5818 msurface_t *surface;
5819 model_t *model = ent->model;
5822 GL_DepthRange(0, 1);
5823 GL_DepthTest(!r_showdisabledepthtest.integer);
5824 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5826 GL_BlendFunc(GL_ONE, GL_ZERO);
5827 R_Mesh_ColorPointer(NULL, 0, 0);
5828 R_Mesh_ResetTextureState();
5829 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5831 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5833 rsurface.texture = surface->texture->currentframe;
5834 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5836 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5839 if (!rsurface.texture->currentlayers->depthmask)
5840 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5841 else if (ent == r_refdef.worldentity)
5842 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5844 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5845 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5848 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5850 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5851 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5852 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5853 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5860 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5862 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5864 VectorCopy(rsurface.vertex3f + l * 3, v);
5865 qglVertex3f(v[0], v[1], v[2]);
5866 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5867 qglVertex3f(v[0], v[1], v[2]);
5871 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5873 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5875 VectorCopy(rsurface.vertex3f + l * 3, v);
5876 qglVertex3f(v[0], v[1], v[2]);
5877 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5878 qglVertex3f(v[0], v[1], v[2]);
5882 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5884 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5886 VectorCopy(rsurface.vertex3f + l * 3, v);
5887 qglVertex3f(v[0], v[1], v[2]);
5888 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5889 qglVertex3f(v[0], v[1], v[2]);
5896 rsurface.texture = NULL;
5899 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5900 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5902 int i, j, endj, f, flagsmask;
5903 int counttriangles = 0;
5904 msurface_t *surface, **surfacechain;
5906 model_t *model = r_refdef.worldmodel;
5907 const int maxsurfacelist = 1024;
5908 int numsurfacelist = 0;
5909 msurface_t *surfacelist[1024];
5913 RSurf_ActiveWorldEntity();
5915 // update light styles
5916 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5918 for (i = 0;i < model->brushq1.light_styles;i++)
5920 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5922 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5923 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5924 for (;(surface = *surfacechain);surfacechain++)
5925 surface->cached_dlight = true;
5930 R_UpdateAllTextureInfo(r_refdef.worldentity);
5931 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
5934 rsurface.uselightmaptexture = false;
5935 rsurface.texture = NULL;
5937 j = model->firstmodelsurface;
5938 endj = j + model->nummodelsurfaces;
5941 // quickly skip over non-visible surfaces
5942 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5944 // quickly iterate over visible surfaces
5945 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5947 // process this surface
5948 surface = model->data_surfaces + j;
5949 // if this surface fits the criteria, add it to the list
5950 if (surface->num_triangles)
5952 // if lightmap parameters changed, rebuild lightmap texture
5953 if (surface->cached_dlight)
5954 R_BuildLightMap(r_refdef.worldentity, surface);
5955 // add face to draw list
5956 surfacelist[numsurfacelist++] = surface;
5957 counttriangles += surface->num_triangles;
5958 if (numsurfacelist >= maxsurfacelist)
5960 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5967 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5968 r_refdef.stats.entities_triangles += counttriangles;
5971 if (r_view.showdebug)
5973 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
5974 R_DrawCollisionBrushes(r_refdef.worldentity);
5976 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
5977 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5981 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5983 int i, f, flagsmask;
5984 int counttriangles = 0;
5985 msurface_t *surface, *endsurface, **surfacechain;
5987 model_t *model = ent->model;
5988 const int maxsurfacelist = 1024;
5989 int numsurfacelist = 0;
5990 msurface_t *surfacelist[1024];
5994 // if the model is static it doesn't matter what value we give for
5995 // wantnormals and wanttangents, so this logic uses only rules applicable
5996 // to a model, knowing that they are meaningless otherwise
5997 if (ent == r_refdef.worldentity)
5998 RSurf_ActiveWorldEntity();
5999 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6000 RSurf_ActiveModelEntity(ent, false, false);
6002 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6004 // update light styles
6005 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6007 for (i = 0;i < model->brushq1.light_styles;i++)
6009 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6011 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6012 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6013 for (;(surface = *surfacechain);surfacechain++)
6014 surface->cached_dlight = true;
6019 R_UpdateAllTextureInfo(ent);
6020 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6023 rsurface.uselightmaptexture = false;
6024 rsurface.texture = NULL;
6026 surface = model->data_surfaces + model->firstmodelsurface;
6027 endsurface = surface + model->nummodelsurfaces;
6028 for (;surface < endsurface;surface++)
6030 // if this surface fits the criteria, add it to the list
6031 if (surface->num_triangles)
6033 // if lightmap parameters changed, rebuild lightmap texture
6034 if (surface->cached_dlight)
6035 R_BuildLightMap(ent, surface);
6036 // add face to draw list
6037 surfacelist[numsurfacelist++] = surface;
6038 counttriangles += surface->num_triangles;
6039 if (numsurfacelist >= maxsurfacelist)
6041 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6047 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6048 r_refdef.stats.entities_triangles += counttriangles;
6051 if (r_view.showdebug)
6053 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
6054 R_DrawCollisionBrushes(ent);
6056 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
6057 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);