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 *= myhalf(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 + 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 + 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 p = r_view.frustum + i;
1854 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1858 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1862 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1866 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1870 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1874 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1878 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1882 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1890 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1894 for (i = 0;i < numplanes;i++)
1901 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1905 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1909 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1913 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1917 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1921 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1925 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1929 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1937 //==================================================================================
1939 static void R_UpdateEntityLighting(entity_render_t *ent)
1941 vec3_t tempdiffusenormal;
1943 // fetch the lighting from the worldmodel data
1944 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));
1945 VectorClear(ent->modellight_diffuse);
1946 VectorClear(tempdiffusenormal);
1947 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1950 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1951 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1954 VectorSet(ent->modellight_ambient, 1, 1, 1);
1956 // move the light direction into modelspace coordinates for lighting code
1957 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1958 if(VectorLength2(ent->modellight_lightdir) > 0)
1960 VectorNormalize(ent->modellight_lightdir);
1964 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1967 // scale ambient and directional light contributions according to rendering variables
1968 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1969 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1970 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1971 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1972 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1973 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1976 static void R_View_UpdateEntityVisible (void)
1979 entity_render_t *ent;
1981 if (!r_drawentities.integer)
1984 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1985 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1987 // worldmodel can check visibility
1988 for (i = 0;i < r_refdef.numentities;i++)
1990 ent = r_refdef.entities[i];
1991 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));
1993 if(r_cullentities_trace.integer)
1995 for (i = 0;i < r_refdef.numentities;i++)
1997 ent = r_refdef.entities[i];
1998 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2000 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2001 ent->last_trace_visibility = realtime;
2002 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2003 r_viewcache.entityvisible[i] = 0;
2010 // no worldmodel or it can't check visibility
2011 for (i = 0;i < r_refdef.numentities;i++)
2013 ent = r_refdef.entities[i];
2014 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2018 // update entity lighting (even on hidden entities for r_shadows)
2019 for (i = 0;i < r_refdef.numentities;i++)
2020 R_UpdateEntityLighting(r_refdef.entities[i]);
2023 // only used if skyrendermasked, and normally returns false
2024 int R_DrawBrushModelsSky (void)
2027 entity_render_t *ent;
2029 if (!r_drawentities.integer)
2033 for (i = 0;i < r_refdef.numentities;i++)
2035 if (!r_viewcache.entityvisible[i])
2037 ent = r_refdef.entities[i];
2038 if (!ent->model || !ent->model->DrawSky)
2040 ent->model->DrawSky(ent);
2046 static void R_DrawNoModel(entity_render_t *ent);
2047 static void R_DrawModels(void)
2050 entity_render_t *ent;
2052 if (!r_drawentities.integer)
2055 for (i = 0;i < r_refdef.numentities;i++)
2057 if (!r_viewcache.entityvisible[i])
2059 ent = r_refdef.entities[i];
2060 r_refdef.stats.entities++;
2061 if (ent->model && ent->model->Draw != NULL)
2062 ent->model->Draw(ent);
2068 static void R_DrawModelsDepth(void)
2071 entity_render_t *ent;
2073 if (!r_drawentities.integer)
2076 for (i = 0;i < r_refdef.numentities;i++)
2078 if (!r_viewcache.entityvisible[i])
2080 ent = r_refdef.entities[i];
2081 r_refdef.stats.entities++;
2082 if (ent->model && ent->model->DrawDepth != NULL)
2083 ent->model->DrawDepth(ent);
2087 static void R_DrawModelsAddWaterPlanes(void)
2090 entity_render_t *ent;
2092 if (!r_drawentities.integer)
2095 for (i = 0;i < r_refdef.numentities;i++)
2097 if (!r_viewcache.entityvisible[i])
2099 ent = r_refdef.entities[i];
2100 r_refdef.stats.entities++;
2101 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2102 ent->model->DrawAddWaterPlanes(ent);
2106 static void R_View_SetFrustum(void)
2109 double slopex, slopey;
2111 // break apart the view matrix into vectors for various purposes
2112 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2113 VectorNegate(r_view.left, r_view.right);
2116 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2117 r_view.frustum[0].normal[1] = 0 - 0;
2118 r_view.frustum[0].normal[2] = -1 - 0;
2119 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2120 r_view.frustum[1].normal[1] = 0 + 0;
2121 r_view.frustum[1].normal[2] = -1 + 0;
2122 r_view.frustum[2].normal[0] = 0 - 0;
2123 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2124 r_view.frustum[2].normal[2] = -1 - 0;
2125 r_view.frustum[3].normal[0] = 0 + 0;
2126 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2127 r_view.frustum[3].normal[2] = -1 + 0;
2131 zNear = r_refdef.nearclip;
2132 nudge = 1.0 - 1.0 / (1<<23);
2133 r_view.frustum[4].normal[0] = 0 - 0;
2134 r_view.frustum[4].normal[1] = 0 - 0;
2135 r_view.frustum[4].normal[2] = -1 - -nudge;
2136 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2137 r_view.frustum[5].normal[0] = 0 + 0;
2138 r_view.frustum[5].normal[1] = 0 + 0;
2139 r_view.frustum[5].normal[2] = -1 + -nudge;
2140 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2146 r_view.frustum[0].normal[0] = m[3] - m[0];
2147 r_view.frustum[0].normal[1] = m[7] - m[4];
2148 r_view.frustum[0].normal[2] = m[11] - m[8];
2149 r_view.frustum[0].dist = m[15] - m[12];
2151 r_view.frustum[1].normal[0] = m[3] + m[0];
2152 r_view.frustum[1].normal[1] = m[7] + m[4];
2153 r_view.frustum[1].normal[2] = m[11] + m[8];
2154 r_view.frustum[1].dist = m[15] + m[12];
2156 r_view.frustum[2].normal[0] = m[3] - m[1];
2157 r_view.frustum[2].normal[1] = m[7] - m[5];
2158 r_view.frustum[2].normal[2] = m[11] - m[9];
2159 r_view.frustum[2].dist = m[15] - m[13];
2161 r_view.frustum[3].normal[0] = m[3] + m[1];
2162 r_view.frustum[3].normal[1] = m[7] + m[5];
2163 r_view.frustum[3].normal[2] = m[11] + m[9];
2164 r_view.frustum[3].dist = m[15] + m[13];
2166 r_view.frustum[4].normal[0] = m[3] - m[2];
2167 r_view.frustum[4].normal[1] = m[7] - m[6];
2168 r_view.frustum[4].normal[2] = m[11] - m[10];
2169 r_view.frustum[4].dist = m[15] - m[14];
2171 r_view.frustum[5].normal[0] = m[3] + m[2];
2172 r_view.frustum[5].normal[1] = m[7] + m[6];
2173 r_view.frustum[5].normal[2] = m[11] + m[10];
2174 r_view.frustum[5].dist = m[15] + m[14];
2179 if (r_view.useperspective)
2181 slopex = 1.0 / r_view.frustum_x;
2182 slopey = 1.0 / r_view.frustum_y;
2183 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2184 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2185 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2186 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2187 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2189 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2190 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2191 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2192 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2193 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2195 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2196 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2197 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2198 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2199 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2203 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2204 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2205 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2206 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2207 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2208 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2209 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2210 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2211 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2212 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2214 r_view.numfrustumplanes = 5;
2216 if (r_view.useclipplane)
2218 r_view.numfrustumplanes = 6;
2219 r_view.frustum[5] = r_view.clipplane;
2222 for (i = 0;i < r_view.numfrustumplanes;i++)
2223 PlaneClassify(r_view.frustum + i);
2225 // LordHavoc: note to all quake engine coders, Quake had a special case
2226 // for 90 degrees which assumed a square view (wrong), so I removed it,
2227 // Quake2 has it disabled as well.
2229 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2230 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2231 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2232 //PlaneClassify(&frustum[0]);
2234 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2235 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2236 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2237 //PlaneClassify(&frustum[1]);
2239 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2240 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2241 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2242 //PlaneClassify(&frustum[2]);
2244 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2245 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2246 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2247 //PlaneClassify(&frustum[3]);
2250 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2251 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2252 //PlaneClassify(&frustum[4]);
2255 void R_View_Update(void)
2257 R_View_SetFrustum();
2258 R_View_WorldVisibility(r_view.useclipplane);
2259 R_View_UpdateEntityVisible();
2262 void R_SetupView(void)
2264 if (!r_view.useperspective)
2265 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);
2266 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2267 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2269 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2271 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2273 if (r_view.useclipplane)
2275 // LordHavoc: couldn't figure out how to make this approach the
2276 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2277 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2278 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2279 dist = r_view.clipplane.dist;
2280 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2284 void R_ResetViewRendering2D(void)
2286 if (gl_support_fragment_shader)
2288 qglUseProgramObjectARB(0);CHECKGLERROR
2293 // GL is weird because it's bottom to top, r_view.y is top to bottom
2294 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2295 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2296 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2297 GL_Color(1, 1, 1, 1);
2298 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2299 GL_BlendFunc(GL_ONE, GL_ZERO);
2300 GL_AlphaTest(false);
2301 GL_ScissorTest(false);
2302 GL_DepthMask(false);
2303 GL_DepthRange(0, 1);
2304 GL_DepthTest(false);
2305 R_Mesh_Matrix(&identitymatrix);
2306 R_Mesh_ResetTextureState();
2307 GL_PolygonOffset(0, 0);
2308 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2309 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2310 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2311 qglStencilMask(~0);CHECKGLERROR
2312 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2313 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2314 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2317 void R_ResetViewRendering3D(void)
2319 if (gl_support_fragment_shader)
2321 qglUseProgramObjectARB(0);CHECKGLERROR
2326 // GL is weird because it's bottom to top, r_view.y is top to bottom
2327 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2329 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2330 GL_Color(1, 1, 1, 1);
2331 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2332 GL_BlendFunc(GL_ONE, GL_ZERO);
2333 GL_AlphaTest(false);
2334 GL_ScissorTest(true);
2336 GL_DepthRange(0, 1);
2338 R_Mesh_Matrix(&identitymatrix);
2339 R_Mesh_ResetTextureState();
2340 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2341 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2342 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2343 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2344 qglStencilMask(~0);CHECKGLERROR
2345 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2346 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2347 GL_CullFace(r_view.cullface_back);
2351 R_Bloom_SetupShader(
2353 "// written by Forest 'LordHavoc' Hale\n"
2355 "// common definitions between vertex shader and fragment shader:\n"
2357 "#ifdef __GLSL_CG_DATA_TYPES\n"
2358 "#define myhalf half\n"
2359 "#define myhvec2 hvec2\n"
2360 "#define myhvec3 hvec3\n"
2361 "#define myhvec4 hvec4\n"
2363 "#define myhalf float\n"
2364 "#define myhvec2 vec2\n"
2365 "#define myhvec3 vec3\n"
2366 "#define myhvec4 vec4\n"
2369 "varying vec2 ScreenTexCoord;\n"
2370 "varying vec2 BloomTexCoord;\n"
2375 "// vertex shader specific:\n"
2376 "#ifdef VERTEX_SHADER\n"
2380 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2381 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2382 " // transform vertex to camera space, using ftransform to match non-VS\n"
2384 " gl_Position = ftransform();\n"
2387 "#endif // VERTEX_SHADER\n"
2392 "// fragment shader specific:\n"
2393 "#ifdef FRAGMENT_SHADER\n"
2398 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2399 " for (x = -BLUR_X;x <= BLUR_X;x++)
2400 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2401 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2402 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2403 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2405 " gl_FragColor = vec4(color);\n"
2408 "#endif // FRAGMENT_SHADER\n"
2411 void R_RenderScene(qboolean addwaterplanes);
2413 static void R_Water_StartFrame(void)
2416 int texturewidth, textureheight;
2417 r_waterstate_waterplane_t *p;
2419 r_waterstate.maxwaterplanes = 0;
2421 // set waterwidth and waterheight to the water resolution that will be
2422 // used (often less than the screen resolution for faster rendering)
2423 r_waterstate.waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2424 r_waterstate.waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2426 // calculate desired texture sizes
2427 if (gl_support_arb_texture_non_power_of_two)
2429 texturewidth = r_waterstate.waterwidth;
2430 textureheight = r_waterstate.waterheight;
2434 for (texturewidth = 1;texturewidth < r_waterstate.waterwidth ;texturewidth *= 2);
2435 for (textureheight = 1;textureheight < r_waterstate.waterheight;textureheight *= 2);
2438 if (!r_glsl_water.integer)
2439 texturewidth = textureheight = 0;
2441 // allocate textures as needed
2442 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2444 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2446 if (p->texture_refraction)
2447 R_FreeTexture(p->texture_refraction);
2448 p->texture_refraction = NULL;
2449 if (p->texture_reflection)
2450 R_FreeTexture(p->texture_reflection);
2451 p->texture_reflection = NULL;
2453 r_waterstate.texturewidth = texturewidth;
2454 r_waterstate.textureheight = textureheight;
2457 if ((!texturewidth && !textureheight) || texturewidth > gl_max_texture_size || textureheight > gl_max_texture_size)
2459 // can't use water if the parameters are too weird
2460 // can't use water if the card does not support the texture size
2461 memset(&r_waterstate, 0, sizeof(r_waterstate));
2465 r_waterstate.enabled = true;
2467 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2469 // set up variables that will be used in shader setup
2470 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2471 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2472 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2473 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2476 static void R_Water_AddWaterPlane(msurface_t *surface)
2478 int triangleindex, planeindex;
2482 r_waterstate_waterplane_t *p;
2483 // just use the first triangle with a valid normal for any decisions
2484 VectorClear(normal);
2485 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2487 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2488 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2489 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2490 TriangleNormal(vert[0], vert[1], vert[2], normal);
2491 if (VectorLength2(normal) >= 0.001)
2494 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2496 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2498 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2502 // if this triangle does not fit any known plane rendered this frame, render textures for it
2503 if (planeindex >= r_waterstate.numwaterplanes && planeindex < r_waterstate.maxwaterplanes)
2505 // store the new plane
2506 r_waterstate.numwaterplanes++;
2507 VectorCopy(normal, p->plane.normal);
2508 VectorNormalize(p->plane.normal);
2509 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2510 PlaneClassify(&p->plane);
2511 // flip the plane if it does not face the viewer
2512 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2514 VectorNegate(p->plane.normal, p->plane.normal);
2515 p->plane.dist *= -1;
2516 PlaneClassify(&p->plane);
2518 p->materialflags = surface->texture->currentframe->currentmaterialflags;
2522 static void R_Water_ProcessPlanes(void)
2524 r_view_t originalview;
2526 r_waterstate_waterplane_t *p;
2528 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2530 if (!p->texture_refraction && (p->materialflags & MATERIALFLAG_WATERSHADER))
2531 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);
2532 if (!p->texture_reflection && (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
2533 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);
2535 originalview = r_view;
2536 r_view.showdebug = false;
2537 r_view.width = r_waterstate.waterwidth;
2538 r_view.height = r_waterstate.waterheight;
2539 r_view.useclipplane = true;
2541 r_view.clipplane = p->plane;
2542 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2543 r_view.clipplane.dist = -r_view.clipplane.dist;
2544 PlaneClassify(&r_view.clipplane);
2545 r_waterstate.renderingscene = true;
2546 // render the normal view scene and copy into texture
2547 // (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)
2548 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2550 R_RenderScene(false);
2552 // copy view into the screen texture
2553 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2554 GL_ActiveTexture(0);
2556 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
2559 // render reflected scene and copy into texture
2560 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2561 r_view.clipplane = p->plane;
2562 // reverse the cullface settings for this render
2563 r_view.cullface_front = GL_FRONT;
2564 r_view.cullface_back = GL_BACK;
2566 R_ResetViewRendering3D();
2569 R_RenderScene(false);
2571 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2572 GL_ActiveTexture(0);
2574 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
2576 R_ResetViewRendering3D();
2579 r_view = originalview;
2580 r_waterstate.renderingscene = false;
2584 void R_Bloom_StartFrame(void)
2586 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2588 // set bloomwidth and bloomheight to the bloom resolution that will be
2589 // used (often less than the screen resolution for faster rendering)
2590 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2591 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2592 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2594 // calculate desired texture sizes
2595 if (gl_support_arb_texture_non_power_of_two)
2597 screentexturewidth = r_view.width;
2598 screentextureheight = r_view.height;
2599 bloomtexturewidth = r_bloomstate.bloomwidth;
2600 bloomtextureheight = r_bloomstate.bloomheight;
2604 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2605 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2606 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2607 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2612 screentexturewidth = screentextureheight = 0;
2614 else if (r_bloom.integer)
2619 screentexturewidth = screentextureheight = 0;
2620 bloomtexturewidth = bloomtextureheight = 0;
2623 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)
2625 // can't use bloom if the parameters are too weird
2626 // can't use bloom if the card does not support the texture size
2627 if (r_bloomstate.texture_screen)
2628 R_FreeTexture(r_bloomstate.texture_screen);
2629 if (r_bloomstate.texture_bloom)
2630 R_FreeTexture(r_bloomstate.texture_bloom);
2631 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2635 r_bloomstate.enabled = true;
2636 r_bloomstate.hdr = r_hdr.integer != 0;
2638 // allocate textures as needed
2639 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2641 if (r_bloomstate.texture_screen)
2642 R_FreeTexture(r_bloomstate.texture_screen);
2643 r_bloomstate.texture_screen = NULL;
2644 r_bloomstate.screentexturewidth = screentexturewidth;
2645 r_bloomstate.screentextureheight = screentextureheight;
2646 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2647 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);
2649 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2651 if (r_bloomstate.texture_bloom)
2652 R_FreeTexture(r_bloomstate.texture_bloom);
2653 r_bloomstate.texture_bloom = NULL;
2654 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2655 r_bloomstate.bloomtextureheight = bloomtextureheight;
2656 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2657 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);
2660 // set up a texcoord array for the full resolution screen image
2661 // (we have to keep this around to copy back during final render)
2662 r_bloomstate.screentexcoord2f[0] = 0;
2663 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2664 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2665 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2666 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2667 r_bloomstate.screentexcoord2f[5] = 0;
2668 r_bloomstate.screentexcoord2f[6] = 0;
2669 r_bloomstate.screentexcoord2f[7] = 0;
2671 // set up a texcoord array for the reduced resolution bloom image
2672 // (which will be additive blended over the screen image)
2673 r_bloomstate.bloomtexcoord2f[0] = 0;
2674 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2675 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2676 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2677 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2678 r_bloomstate.bloomtexcoord2f[5] = 0;
2679 r_bloomstate.bloomtexcoord2f[6] = 0;
2680 r_bloomstate.bloomtexcoord2f[7] = 0;
2683 void R_Bloom_CopyScreenTexture(float colorscale)
2685 r_refdef.stats.bloom++;
2687 R_ResetViewRendering2D();
2688 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2689 R_Mesh_ColorPointer(NULL, 0, 0);
2690 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2691 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2693 // copy view into the screen texture
2694 GL_ActiveTexture(0);
2696 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
2697 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2699 // now scale it down to the bloom texture size
2701 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2702 GL_BlendFunc(GL_ONE, GL_ZERO);
2703 GL_Color(colorscale, colorscale, colorscale, 1);
2704 // TODO: optimize with multitexture or GLSL
2705 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2706 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2708 // we now have a bloom image in the framebuffer
2709 // copy it into the bloom image texture for later processing
2710 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2711 GL_ActiveTexture(0);
2713 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
2714 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2717 void R_Bloom_CopyHDRTexture(void)
2719 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2720 GL_ActiveTexture(0);
2722 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
2723 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2726 void R_Bloom_MakeTexture(void)
2729 float xoffset, yoffset, r, brighten;
2731 r_refdef.stats.bloom++;
2733 R_ResetViewRendering2D();
2734 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2735 R_Mesh_ColorPointer(NULL, 0, 0);
2737 // we have a bloom image in the framebuffer
2739 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2741 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2744 r = bound(0, r_bloom_colorexponent.value / x, 1);
2745 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2746 GL_Color(r, r, r, 1);
2747 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2748 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2749 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2750 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2752 // copy the vertically blurred bloom view to a texture
2753 GL_ActiveTexture(0);
2755 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
2756 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2759 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2760 brighten = r_bloom_brighten.value;
2762 brighten *= r_hdr_range.value;
2763 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2764 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2766 for (dir = 0;dir < 2;dir++)
2768 // blend on at multiple vertical offsets to achieve a vertical blur
2769 // TODO: do offset blends using GLSL
2770 GL_BlendFunc(GL_ONE, GL_ZERO);
2771 for (x = -range;x <= range;x++)
2773 if (!dir){xoffset = 0;yoffset = x;}
2774 else {xoffset = x;yoffset = 0;}
2775 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2776 yoffset /= (float)r_bloomstate.bloomtextureheight;
2777 // compute a texcoord array with the specified x and y offset
2778 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2779 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2780 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2781 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2782 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2783 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2784 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2785 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2786 // this r value looks like a 'dot' particle, fading sharply to
2787 // black at the edges
2788 // (probably not realistic but looks good enough)
2789 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2790 //r = (dir ? 1.0f : brighten)/(range*2+1);
2791 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2792 GL_Color(r, r, r, 1);
2793 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2794 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2795 GL_BlendFunc(GL_ONE, GL_ONE);
2798 // copy the vertically blurred bloom view to a texture
2799 GL_ActiveTexture(0);
2801 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
2802 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2805 // apply subtract last
2806 // (just like it would be in a GLSL shader)
2807 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2809 GL_BlendFunc(GL_ONE, GL_ZERO);
2810 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2811 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2812 GL_Color(1, 1, 1, 1);
2813 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2814 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2816 GL_BlendFunc(GL_ONE, GL_ONE);
2817 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2818 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2819 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2820 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2821 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2822 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2823 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2825 // copy the darkened bloom view to a texture
2826 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2827 GL_ActiveTexture(0);
2829 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
2830 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2834 void R_HDR_RenderBloomTexture(void)
2836 int oldwidth, oldheight;
2838 oldwidth = r_view.width;
2839 oldheight = r_view.height;
2840 r_view.width = r_bloomstate.bloomwidth;
2841 r_view.height = r_bloomstate.bloomheight;
2843 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2844 // TODO: add exposure compensation features
2845 // TODO: add fp16 framebuffer support
2847 r_view.showdebug = false;
2848 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2850 r_view.colorscale /= r_hdr_range.value;
2851 r_waterstate.numwaterplanes = 0;
2852 R_RenderScene(r_waterstate.enabled);
2853 r_view.showdebug = true;
2855 R_ResetViewRendering2D();
2857 R_Bloom_CopyHDRTexture();
2858 R_Bloom_MakeTexture();
2860 R_ResetViewRendering3D();
2863 if (r_timereport_active)
2864 R_TimeReport("clear");
2867 // restore the view settings
2868 r_view.width = oldwidth;
2869 r_view.height = oldheight;
2872 static void R_BlendView(void)
2874 if (r_bloomstate.enabled && r_bloomstate.hdr)
2876 // render high dynamic range bloom effect
2877 // the bloom texture was made earlier this render, so we just need to
2878 // blend it onto the screen...
2879 R_ResetViewRendering2D();
2880 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2881 R_Mesh_ColorPointer(NULL, 0, 0);
2882 GL_Color(1, 1, 1, 1);
2883 GL_BlendFunc(GL_ONE, GL_ONE);
2884 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2885 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2886 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2887 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2889 else if (r_bloomstate.enabled)
2891 // render simple bloom effect
2892 // copy the screen and shrink it and darken it for the bloom process
2893 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2894 // make the bloom texture
2895 R_Bloom_MakeTexture();
2896 // put the original screen image back in place and blend the bloom
2898 R_ResetViewRendering2D();
2899 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2900 R_Mesh_ColorPointer(NULL, 0, 0);
2901 GL_Color(1, 1, 1, 1);
2902 GL_BlendFunc(GL_ONE, GL_ZERO);
2903 // do both in one pass if possible
2904 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2905 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2906 if (r_textureunits.integer >= 2 && gl_combine.integer)
2908 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2909 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2910 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2914 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2915 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2916 // now blend on the bloom texture
2917 GL_BlendFunc(GL_ONE, GL_ONE);
2918 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2919 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2921 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2922 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2924 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2926 // apply a color tint to the whole view
2927 R_ResetViewRendering2D();
2928 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2929 R_Mesh_ColorPointer(NULL, 0, 0);
2930 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2931 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2932 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2936 void R_RenderScene(qboolean addwaterplanes);
2938 matrix4x4_t r_waterscrollmatrix;
2940 void R_UpdateVariables(void)
2944 r_refdef.farclip = 4096;
2945 if (r_refdef.worldmodel)
2946 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2947 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2949 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
2950 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
2951 r_refdef.polygonfactor = 0;
2952 r_refdef.polygonoffset = 0;
2953 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2954 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
2956 r_refdef.rtworld = r_shadow_realtime_world.integer;
2957 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2958 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2959 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
2960 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2961 if (r_showsurfaces.integer)
2963 r_refdef.rtworld = false;
2964 r_refdef.rtworldshadows = false;
2965 r_refdef.rtdlight = false;
2966 r_refdef.rtdlightshadows = false;
2967 r_refdef.lightmapintensity = 0;
2970 if (gamemode == GAME_NEHAHRA)
2972 if (gl_fogenable.integer)
2974 r_refdef.oldgl_fogenable = true;
2975 r_refdef.fog_density = gl_fogdensity.value;
2976 r_refdef.fog_red = gl_fogred.value;
2977 r_refdef.fog_green = gl_foggreen.value;
2978 r_refdef.fog_blue = gl_fogblue.value;
2980 else if (r_refdef.oldgl_fogenable)
2982 r_refdef.oldgl_fogenable = false;
2983 r_refdef.fog_density = 0;
2984 r_refdef.fog_red = 0;
2985 r_refdef.fog_green = 0;
2986 r_refdef.fog_blue = 0;
2989 if (r_refdef.fog_density)
2991 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2992 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2993 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2995 if (r_refdef.fog_density)
2997 r_refdef.fogenabled = true;
2998 // this is the point where the fog reaches 0.9986 alpha, which we
2999 // consider a good enough cutoff point for the texture
3000 // (0.9986 * 256 == 255.6)
3001 r_refdef.fogrange = 400 / r_refdef.fog_density;
3002 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3003 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3004 // fog color was already set
3007 r_refdef.fogenabled = false;
3015 void R_RenderView(void)
3017 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3018 return; //Host_Error ("R_RenderView: NULL worldmodel");
3020 R_Shadow_UpdateWorldLightSelection();
3022 R_Bloom_StartFrame();
3023 R_Water_StartFrame();
3026 if (r_timereport_active)
3027 R_TimeReport("setup");
3029 R_ResetViewRendering3D();
3032 if (r_timereport_active)
3033 R_TimeReport("clear");
3035 r_view.showdebug = true;
3037 // this produces a bloom texture to be used in R_BlendView() later
3039 R_HDR_RenderBloomTexture();
3041 r_view.colorscale = r_hdr_scenebrightness.value;
3042 r_waterstate.numwaterplanes = 0;
3043 R_RenderScene(r_waterstate.enabled);
3046 if (r_timereport_active)
3047 R_TimeReport("blendview");
3049 GL_Scissor(0, 0, vid.width, vid.height);
3050 GL_ScissorTest(false);
3054 extern void R_DrawLightningBeams (void);
3055 extern void VM_CL_AddPolygonsToMeshQueue (void);
3056 extern void R_DrawPortals (void);
3057 extern cvar_t cl_locs_show;
3058 static void R_DrawLocs(void);
3059 static void R_DrawEntityBBoxes(void);
3060 void R_RenderScene(qboolean addwaterplanes)
3064 R_ResetViewRendering3D();
3067 if (r_timereport_active)
3068 R_TimeReport("watervisibility");
3070 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3072 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3073 if (r_timereport_active)
3074 R_TimeReport("waterworld");
3077 // don't let sound skip if going slow
3078 if (r_refdef.extraupdate)
3081 R_DrawModelsAddWaterPlanes();
3082 if (r_timereport_active)
3083 R_TimeReport("watermodels");
3085 R_Water_ProcessPlanes();
3086 if (r_timereport_active)
3087 R_TimeReport("waterscenes");
3090 R_ResetViewRendering3D();
3092 // don't let sound skip if going slow
3093 if (r_refdef.extraupdate)
3096 R_MeshQueue_BeginScene();
3101 if (r_timereport_active)
3102 R_TimeReport("visibility");
3104 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);
3106 if (cl.csqc_vidvars.drawworld)
3108 // don't let sound skip if going slow
3109 if (r_refdef.extraupdate)
3112 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3114 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3115 if (r_timereport_active)
3116 R_TimeReport("worldsky");
3119 if (R_DrawBrushModelsSky() && r_timereport_active)
3120 R_TimeReport("bmodelsky");
3123 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3125 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3126 if (r_timereport_active)
3127 R_TimeReport("worlddepth");
3129 if (r_depthfirst.integer >= 2)
3131 R_DrawModelsDepth();
3132 if (r_timereport_active)
3133 R_TimeReport("modeldepth");
3136 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3138 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3139 if (r_timereport_active)
3140 R_TimeReport("world");
3143 // don't let sound skip if going slow
3144 if (r_refdef.extraupdate)
3148 if (r_timereport_active)
3149 R_TimeReport("models");
3151 // don't let sound skip if going slow
3152 if (r_refdef.extraupdate)
3155 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3157 R_DrawModelShadows();
3159 R_ResetViewRendering3D();
3161 // don't let sound skip if going slow
3162 if (r_refdef.extraupdate)
3166 R_ShadowVolumeLighting(false);
3167 if (r_timereport_active)
3168 R_TimeReport("rtlights");
3170 // don't let sound skip if going slow
3171 if (r_refdef.extraupdate)
3174 if (cl.csqc_vidvars.drawworld)
3176 R_DrawLightningBeams();
3177 if (r_timereport_active)
3178 R_TimeReport("lightning");
3181 if (r_timereport_active)
3182 R_TimeReport("particles");
3185 if (r_timereport_active)
3186 R_TimeReport("explosions");
3189 if (gl_support_fragment_shader)
3191 qglUseProgramObjectARB(0);CHECKGLERROR
3193 VM_CL_AddPolygonsToMeshQueue();
3195 if (r_view.showdebug)
3197 if (cl_locs_show.integer)
3200 if (r_timereport_active)
3201 R_TimeReport("showlocs");
3204 if (r_drawportals.integer)
3207 if (r_timereport_active)
3208 R_TimeReport("portals");
3211 if (r_showbboxes.value > 0)
3213 R_DrawEntityBBoxes();
3214 if (r_timereport_active)
3215 R_TimeReport("bboxes");
3219 if (gl_support_fragment_shader)
3221 qglUseProgramObjectARB(0);CHECKGLERROR
3223 R_MeshQueue_RenderTransparent();
3224 if (r_timereport_active)
3225 R_TimeReport("drawtrans");
3227 if (gl_support_fragment_shader)
3229 qglUseProgramObjectARB(0);CHECKGLERROR
3232 if (cl.csqc_vidvars.drawworld)
3235 if (r_timereport_active)
3236 R_TimeReport("coronas");
3239 // don't let sound skip if going slow
3240 if (r_refdef.extraupdate)
3243 R_ResetViewRendering2D();
3246 static const int bboxelements[36] =
3256 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3259 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3260 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3261 GL_DepthMask(false);
3262 GL_DepthRange(0, 1);
3263 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3264 R_Mesh_Matrix(&identitymatrix);
3265 R_Mesh_ResetTextureState();
3267 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3268 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3269 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3270 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3271 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3272 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3273 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3274 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3275 R_FillColors(color4f, 8, cr, cg, cb, ca);
3276 if (r_refdef.fogenabled)
3278 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3280 f1 = FogPoint_World(v);
3282 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3283 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3284 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3287 R_Mesh_VertexPointer(vertex3f, 0, 0);
3288 R_Mesh_ColorPointer(color4f, 0, 0);
3289 R_Mesh_ResetTextureState();
3290 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3293 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3297 prvm_edict_t *edict;
3298 // this function draws bounding boxes of server entities
3302 for (i = 0;i < numsurfaces;i++)
3304 edict = PRVM_EDICT_NUM(surfacelist[i]);
3305 switch ((int)edict->fields.server->solid)
3307 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3308 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3309 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3310 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3311 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3312 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3314 color[3] *= r_showbboxes.value;
3315 color[3] = bound(0, color[3], 1);
3316 GL_DepthTest(!r_showdisabledepthtest.integer);
3317 GL_CullFace(r_view.cullface_front);
3318 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3323 static void R_DrawEntityBBoxes(void)
3326 prvm_edict_t *edict;
3328 // this function draws bounding boxes of server entities
3332 for (i = 0;i < prog->num_edicts;i++)
3334 edict = PRVM_EDICT_NUM(i);
3335 if (edict->priv.server->free)
3337 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3338 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3343 int nomodelelements[24] =
3355 float nomodelvertex3f[6*3] =
3365 float nomodelcolor4f[6*4] =
3367 0.0f, 0.0f, 0.5f, 1.0f,
3368 0.0f, 0.0f, 0.5f, 1.0f,
3369 0.0f, 0.5f, 0.0f, 1.0f,
3370 0.0f, 0.5f, 0.0f, 1.0f,
3371 0.5f, 0.0f, 0.0f, 1.0f,
3372 0.5f, 0.0f, 0.0f, 1.0f
3375 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3380 // this is only called once per entity so numsurfaces is always 1, and
3381 // surfacelist is always {0}, so this code does not handle batches
3382 R_Mesh_Matrix(&ent->matrix);
3384 if (ent->flags & EF_ADDITIVE)
3386 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3387 GL_DepthMask(false);
3389 else if (ent->alpha < 1)
3391 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3392 GL_DepthMask(false);
3396 GL_BlendFunc(GL_ONE, GL_ZERO);
3399 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3400 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3401 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3402 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3403 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3404 if (r_refdef.fogenabled)
3407 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3408 R_Mesh_ColorPointer(color4f, 0, 0);
3409 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3410 f1 = FogPoint_World(org);
3412 for (i = 0, c = color4f;i < 6;i++, c += 4)
3414 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3415 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3416 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3420 else if (ent->alpha != 1)
3422 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3423 R_Mesh_ColorPointer(color4f, 0, 0);
3424 for (i = 0, c = color4f;i < 6;i++, c += 4)
3428 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3429 R_Mesh_ResetTextureState();
3430 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3433 void R_DrawNoModel(entity_render_t *ent)
3436 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3437 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3438 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3440 // R_DrawNoModelCallback(ent, 0);
3443 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3445 vec3_t right1, right2, diff, normal;
3447 VectorSubtract (org2, org1, normal);
3449 // calculate 'right' vector for start
3450 VectorSubtract (r_view.origin, org1, diff);
3451 CrossProduct (normal, diff, right1);
3452 VectorNormalize (right1);
3454 // calculate 'right' vector for end
3455 VectorSubtract (r_view.origin, org2, diff);
3456 CrossProduct (normal, diff, right2);
3457 VectorNormalize (right2);
3459 vert[ 0] = org1[0] + width * right1[0];
3460 vert[ 1] = org1[1] + width * right1[1];
3461 vert[ 2] = org1[2] + width * right1[2];
3462 vert[ 3] = org1[0] - width * right1[0];
3463 vert[ 4] = org1[1] - width * right1[1];
3464 vert[ 5] = org1[2] - width * right1[2];
3465 vert[ 6] = org2[0] - width * right2[0];
3466 vert[ 7] = org2[1] - width * right2[1];
3467 vert[ 8] = org2[2] - width * right2[2];
3468 vert[ 9] = org2[0] + width * right2[0];
3469 vert[10] = org2[1] + width * right2[1];
3470 vert[11] = org2[2] + width * right2[2];
3473 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3475 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)
3480 if (r_refdef.fogenabled)
3481 fog = FogPoint_World(origin);
3483 R_Mesh_Matrix(&identitymatrix);
3484 GL_BlendFunc(blendfunc1, blendfunc2);
3490 GL_CullFace(r_view.cullface_front);
3493 GL_CullFace(r_view.cullface_back);
3495 GL_DepthMask(false);
3496 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3497 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3498 GL_DepthTest(!depthdisable);
3500 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3501 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3502 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3503 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3504 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3505 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3506 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3507 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3508 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3509 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3510 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3511 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3513 R_Mesh_VertexPointer(vertex3f, 0, 0);
3514 R_Mesh_ColorPointer(NULL, 0, 0);
3515 R_Mesh_ResetTextureState();
3516 R_Mesh_TexBind(0, R_GetTexture(texture));
3517 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3518 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3519 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3520 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3522 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3524 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3525 GL_BlendFunc(blendfunc1, GL_ONE);
3527 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);
3528 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3532 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3537 VectorSet(v, x, y, z);
3538 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3539 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3541 if (i == mesh->numvertices)
3543 if (mesh->numvertices < mesh->maxvertices)
3545 VectorCopy(v, vertex3f);
3546 mesh->numvertices++;
3548 return mesh->numvertices;
3554 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3558 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3559 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3560 e = mesh->element3i + mesh->numtriangles * 3;
3561 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3563 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3564 if (mesh->numtriangles < mesh->maxtriangles)
3569 mesh->numtriangles++;
3571 element[1] = element[2];
3575 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3579 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3580 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3581 e = mesh->element3i + mesh->numtriangles * 3;
3582 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3584 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3585 if (mesh->numtriangles < mesh->maxtriangles)
3590 mesh->numtriangles++;
3592 element[1] = element[2];
3596 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3597 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3599 int planenum, planenum2;
3602 mplane_t *plane, *plane2;
3604 double temppoints[2][256*3];
3605 // figure out how large a bounding box we need to properly compute this brush
3607 for (w = 0;w < numplanes;w++)
3608 maxdist = max(maxdist, planes[w].dist);
3609 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3610 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3611 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3615 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3616 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3618 if (planenum2 == planenum)
3620 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);
3623 if (tempnumpoints < 3)
3625 // generate elements forming a triangle fan for this polygon
3626 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3630 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3633 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3634 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3635 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);
3636 GL_LockArrays(0, brush->numpoints);
3637 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3638 GL_LockArrays(0, 0);
3641 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3644 if (!surface->num_collisiontriangles)
3646 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3647 i = (int)(((size_t)surface) / sizeof(msurface_t));
3648 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);
3649 GL_LockArrays(0, surface->num_collisionvertices);
3650 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3651 GL_LockArrays(0, 0);
3654 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)
3656 texturelayer_t *layer;
3657 layer = t->currentlayers + t->currentnumlayers++;
3659 layer->depthmask = depthmask;
3660 layer->blendfunc1 = blendfunc1;
3661 layer->blendfunc2 = blendfunc2;
3662 layer->texture = texture;
3663 layer->texmatrix = *matrix;
3664 layer->color[0] = r * r_view.colorscale;
3665 layer->color[1] = g * r_view.colorscale;
3666 layer->color[2] = b * r_view.colorscale;
3667 layer->color[3] = a;
3670 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3673 index = parms[2] + r_refdef.time * parms[3];
3674 index -= floor(index);
3678 case Q3WAVEFUNC_NONE:
3679 case Q3WAVEFUNC_NOISE:
3680 case Q3WAVEFUNC_COUNT:
3683 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3684 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3685 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3686 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3687 case Q3WAVEFUNC_TRIANGLE:
3689 f = index - floor(index);
3700 return (float)(parms[0] + parms[1] * f);
3703 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3706 model_t *model = ent->model;
3709 q3shaderinfo_layer_tcmod_t *tcmod;
3711 // switch to an alternate material if this is a q1bsp animated material
3713 texture_t *texture = t;
3714 int s = ent->skinnum;
3715 if ((unsigned int)s >= (unsigned int)model->numskins)
3717 if (model->skinscenes)
3719 if (model->skinscenes[s].framecount > 1)
3720 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3722 s = model->skinscenes[s].firstframe;
3725 t = t + s * model->num_surfaces;
3728 // use an alternate animation if the entity's frame is not 0,
3729 // and only if the texture has an alternate animation
3730 if (ent->frame2 != 0 && t->anim_total[1])
3731 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3733 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3735 texture->currentframe = t;
3738 // update currentskinframe to be a qw skin or animation frame
3739 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3741 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3743 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3744 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3745 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);
3747 t->currentskinframe = r_qwskincache_skinframe[i];
3748 if (t->currentskinframe == NULL)
3749 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3751 else if (t->numskinframes >= 2)
3752 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3753 if (t->backgroundnumskinframes >= 2)
3754 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3756 t->currentmaterialflags = t->basematerialflags;
3757 t->currentalpha = ent->alpha;
3758 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3760 t->currentalpha *= r_wateralpha.value;
3761 // if rendering refraction/reflection, disable transparency
3762 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3763 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3765 if (!(ent->flags & RENDER_LIGHT))
3766 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3767 if (ent->effects & EF_ADDITIVE)
3768 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3769 else if (t->currentalpha < 1)
3770 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3771 if (ent->effects & EF_DOUBLESIDED)
3772 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3773 if (ent->effects & EF_NODEPTHTEST)
3774 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3775 if (ent->flags & RENDER_VIEWMODEL)
3776 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3777 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3778 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3779 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3780 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3782 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3785 switch(tcmod->tcmod)
3789 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3790 matrix = r_waterscrollmatrix;
3792 matrix = identitymatrix;
3794 case Q3TCMOD_ENTITYTRANSLATE:
3795 // this is used in Q3 to allow the gamecode to control texcoord
3796 // scrolling on the entity, which is not supported in darkplaces yet.
3797 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3799 case Q3TCMOD_ROTATE:
3800 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3801 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3802 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3805 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3807 case Q3TCMOD_SCROLL:
3808 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3810 case Q3TCMOD_STRETCH:
3811 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3812 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3814 case Q3TCMOD_TRANSFORM:
3815 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3816 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3817 VectorSet(tcmat + 6, 0 , 0 , 1);
3818 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3819 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3821 case Q3TCMOD_TURBULENT:
3822 // this is handled in the RSurf_PrepareVertices function
3823 matrix = identitymatrix;
3826 // either replace or concatenate the transformation
3828 t->currenttexmatrix = matrix;
3831 matrix4x4_t temp = t->currenttexmatrix;
3832 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3836 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3837 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3838 t->glosstexture = r_texture_white;
3839 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3840 t->backgroundglosstexture = r_texture_white;
3841 t->specularpower = r_shadow_glossexponent.value;
3842 // TODO: store reference values for these in the texture?
3843 t->specularscale = 0;
3844 if (r_shadow_gloss.integer > 0)
3846 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3848 if (r_shadow_glossintensity.value > 0)
3850 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3851 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3852 t->specularscale = r_shadow_glossintensity.value;
3855 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3856 t->specularscale = r_shadow_gloss2intensity.value;
3859 // lightmaps mode looks bad with dlights using actual texturing, so turn
3860 // off the colormap and glossmap, but leave the normalmap on as it still
3861 // accurately represents the shading involved
3862 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3864 t->basetexture = r_texture_white;
3865 t->specularscale = 0;
3868 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3869 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3870 // submodels are biased to avoid z-fighting with world surfaces that they
3871 // may be exactly overlapping (avoids z-fighting artifacts on certain
3872 // doors and things in Quake maps)
3873 if (ent->model->brush.submodel)
3875 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3876 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3879 VectorClear(t->dlightcolor);
3880 t->currentnumlayers = 0;
3881 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3883 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3885 int blendfunc1, blendfunc2, depthmask;
3886 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3888 blendfunc1 = GL_SRC_ALPHA;
3889 blendfunc2 = GL_ONE;
3891 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3893 blendfunc1 = GL_SRC_ALPHA;
3894 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3896 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3898 blendfunc1 = t->customblendfunc[0];
3899 blendfunc2 = t->customblendfunc[1];
3903 blendfunc1 = GL_ONE;
3904 blendfunc2 = GL_ZERO;
3906 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3907 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3909 rtexture_t *currentbasetexture;
3911 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3912 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3913 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3914 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3916 // fullbright is not affected by r_refdef.lightmapintensity
3917 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3918 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3919 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);
3920 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3921 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);
3926 // set the color tint used for lights affecting this surface
3927 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3929 // q3bsp has no lightmap updates, so the lightstylevalue that
3930 // would normally be baked into the lightmap must be
3931 // applied to the color
3932 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
3933 if (ent->model->type == mod_brushq3)
3934 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3935 colorscale *= r_refdef.lightmapintensity;
3936 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);
3937 if (r_ambient.value >= (1.0f/64.0f))
3938 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);
3939 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3941 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);
3942 if (r_ambient.value >= (1.0f/64.0f))
3943 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);
3945 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3947 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);
3948 if (r_ambient.value >= (1.0f/64.0f))
3949 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);
3952 if (t->currentskinframe->glow != NULL)
3953 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);
3954 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3956 // if this is opaque use alpha blend which will darken the earlier
3959 // if this is an alpha blended material, all the earlier passes
3960 // were darkened by fog already, so we only need to add the fog
3961 // color ontop through the fog mask texture
3963 // if this is an additive blended material, all the earlier passes
3964 // were darkened by fog already, and we should not add fog color
3965 // (because the background was not darkened, there is no fog color
3966 // that was lost behind it).
3967 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);
3974 void R_UpdateAllTextureInfo(entity_render_t *ent)
3978 for (i = 0;i < ent->model->num_texturesperskin;i++)
3979 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3982 rsurfacestate_t rsurface;
3984 void R_Mesh_ResizeArrays(int newvertices)
3987 if (rsurface.array_size >= newvertices)
3989 if (rsurface.array_modelvertex3f)
3990 Mem_Free(rsurface.array_modelvertex3f);
3991 rsurface.array_size = (newvertices + 1023) & ~1023;
3992 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
3993 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
3994 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
3995 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
3996 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
3997 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
3998 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
3999 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4000 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4001 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4002 rsurface.array_color4f = base + rsurface.array_size * 27;
4003 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4006 void RSurf_CleanUp(void)
4009 if (rsurface.mode == RSURFMODE_GLSL)
4011 qglUseProgramObjectARB(0);CHECKGLERROR
4013 GL_AlphaTest(false);
4014 rsurface.mode = RSURFMODE_NONE;
4015 rsurface.uselightmaptexture = false;
4016 rsurface.texture = NULL;
4019 void RSurf_ActiveWorldEntity(void)
4021 model_t *model = r_refdef.worldmodel;
4023 if (rsurface.array_size < model->surfmesh.num_vertices)
4024 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4025 rsurface.matrix = identitymatrix;
4026 rsurface.inversematrix = identitymatrix;
4027 R_Mesh_Matrix(&identitymatrix);
4028 VectorCopy(r_view.origin, rsurface.modelorg);
4029 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4030 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4031 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4032 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4033 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4034 rsurface.frameblend[0].frame = 0;
4035 rsurface.frameblend[0].lerp = 1;
4036 rsurface.frameblend[1].frame = 0;
4037 rsurface.frameblend[1].lerp = 0;
4038 rsurface.frameblend[2].frame = 0;
4039 rsurface.frameblend[2].lerp = 0;
4040 rsurface.frameblend[3].frame = 0;
4041 rsurface.frameblend[3].lerp = 0;
4042 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4043 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4044 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4045 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4046 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4047 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4048 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4049 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4050 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4051 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4052 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4053 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4054 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4055 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4056 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4057 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4058 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4059 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4060 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4061 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4062 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4063 rsurface.modelelement3i = model->surfmesh.data_element3i;
4064 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4065 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4066 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4067 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4068 rsurface.modelsurfaces = model->data_surfaces;
4069 rsurface.generatedvertex = false;
4070 rsurface.vertex3f = rsurface.modelvertex3f;
4071 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4072 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4073 rsurface.svector3f = rsurface.modelsvector3f;
4074 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4075 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4076 rsurface.tvector3f = rsurface.modeltvector3f;
4077 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4078 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4079 rsurface.normal3f = rsurface.modelnormal3f;
4080 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4081 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4082 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4085 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4087 model_t *model = ent->model;
4089 if (rsurface.array_size < model->surfmesh.num_vertices)
4090 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4091 rsurface.matrix = ent->matrix;
4092 rsurface.inversematrix = ent->inversematrix;
4093 R_Mesh_Matrix(&rsurface.matrix);
4094 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4095 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4096 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4097 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4098 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4099 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4100 rsurface.frameblend[0] = ent->frameblend[0];
4101 rsurface.frameblend[1] = ent->frameblend[1];
4102 rsurface.frameblend[2] = ent->frameblend[2];
4103 rsurface.frameblend[3] = ent->frameblend[3];
4104 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4108 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4109 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4110 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4111 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4112 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4114 else if (wantnormals)
4116 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4117 rsurface.modelsvector3f = NULL;
4118 rsurface.modeltvector3f = NULL;
4119 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4120 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4124 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4125 rsurface.modelsvector3f = NULL;
4126 rsurface.modeltvector3f = NULL;
4127 rsurface.modelnormal3f = NULL;
4128 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4130 rsurface.modelvertex3f_bufferobject = 0;
4131 rsurface.modelvertex3f_bufferoffset = 0;
4132 rsurface.modelsvector3f_bufferobject = 0;
4133 rsurface.modelsvector3f_bufferoffset = 0;
4134 rsurface.modeltvector3f_bufferobject = 0;
4135 rsurface.modeltvector3f_bufferoffset = 0;
4136 rsurface.modelnormal3f_bufferobject = 0;
4137 rsurface.modelnormal3f_bufferoffset = 0;
4138 rsurface.generatedvertex = true;
4142 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4143 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4144 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4145 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4146 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4147 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4148 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4149 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4150 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4151 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4152 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4153 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4154 rsurface.generatedvertex = false;
4156 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4157 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4158 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4159 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4160 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4161 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4162 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4163 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4164 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4165 rsurface.modelelement3i = model->surfmesh.data_element3i;
4166 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4167 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4168 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4169 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4170 rsurface.modelsurfaces = model->data_surfaces;
4171 rsurface.vertex3f = rsurface.modelvertex3f;
4172 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4173 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4174 rsurface.svector3f = rsurface.modelsvector3f;
4175 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4176 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4177 rsurface.tvector3f = rsurface.modeltvector3f;
4178 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4179 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4180 rsurface.normal3f = rsurface.modelnormal3f;
4181 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4182 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4183 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4186 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4187 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4190 int texturesurfaceindex;
4195 const float *v1, *in_tc;
4197 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4199 q3shaderinfo_deform_t *deform;
4200 // 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
4201 if (rsurface.generatedvertex)
4203 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4204 generatenormals = true;
4205 for (i = 0;i < Q3MAXDEFORMS;i++)
4207 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4209 generatetangents = true;
4210 generatenormals = true;
4212 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4213 generatenormals = true;
4215 if (generatenormals && !rsurface.modelnormal3f)
4217 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4218 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4219 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4220 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4222 if (generatetangents && !rsurface.modelsvector3f)
4224 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4225 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4226 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4227 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4228 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4229 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4230 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);
4233 rsurface.vertex3f = rsurface.modelvertex3f;
4234 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4235 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4236 rsurface.svector3f = rsurface.modelsvector3f;
4237 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4238 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4239 rsurface.tvector3f = rsurface.modeltvector3f;
4240 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4241 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4242 rsurface.normal3f = rsurface.modelnormal3f;
4243 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4244 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4245 // if vertices are deformed (sprite flares and things in maps, possibly
4246 // water waves, bulges and other deformations), generate them into
4247 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4248 // (may be static model data or generated data for an animated model, or
4249 // the previous deform pass)
4250 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4252 switch (deform->deform)
4255 case Q3DEFORM_PROJECTIONSHADOW:
4256 case Q3DEFORM_TEXT0:
4257 case Q3DEFORM_TEXT1:
4258 case Q3DEFORM_TEXT2:
4259 case Q3DEFORM_TEXT3:
4260 case Q3DEFORM_TEXT4:
4261 case Q3DEFORM_TEXT5:
4262 case Q3DEFORM_TEXT6:
4263 case Q3DEFORM_TEXT7:
4266 case Q3DEFORM_AUTOSPRITE:
4267 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4268 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4269 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4270 VectorNormalize(newforward);
4271 VectorNormalize(newright);
4272 VectorNormalize(newup);
4273 // make deformed versions of only the model vertices used by the specified surfaces
4274 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4276 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4277 // a single autosprite surface can contain multiple sprites...
4278 for (j = 0;j < surface->num_vertices - 3;j += 4)
4280 VectorClear(center);
4281 for (i = 0;i < 4;i++)
4282 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4283 VectorScale(center, 0.25f, center);
4284 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4285 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4286 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4287 for (i = 0;i < 4;i++)
4289 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4290 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4293 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);
4294 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);
4296 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4297 rsurface.vertex3f_bufferobject = 0;
4298 rsurface.vertex3f_bufferoffset = 0;
4299 rsurface.svector3f = rsurface.array_deformedsvector3f;
4300 rsurface.svector3f_bufferobject = 0;
4301 rsurface.svector3f_bufferoffset = 0;
4302 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4303 rsurface.tvector3f_bufferobject = 0;
4304 rsurface.tvector3f_bufferoffset = 0;
4305 rsurface.normal3f = rsurface.array_deformednormal3f;
4306 rsurface.normal3f_bufferobject = 0;
4307 rsurface.normal3f_bufferoffset = 0;
4309 case Q3DEFORM_AUTOSPRITE2:
4310 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4311 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4312 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4313 VectorNormalize(newforward);
4314 VectorNormalize(newright);
4315 VectorNormalize(newup);
4316 // make deformed versions of only the model vertices used by the specified surfaces
4317 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4319 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4320 const float *v1, *v2;
4330 memset(shortest, 0, sizeof(shortest));
4331 // a single autosprite surface can contain multiple sprites...
4332 for (j = 0;j < surface->num_vertices - 3;j += 4)
4334 VectorClear(center);
4335 for (i = 0;i < 4;i++)
4336 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4337 VectorScale(center, 0.25f, center);
4338 // find the two shortest edges, then use them to define the
4339 // axis vectors for rotating around the central axis
4340 for (i = 0;i < 6;i++)
4342 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4343 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4345 Debug_PolygonBegin(NULL, 0, false, 0);
4346 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4347 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);
4348 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4351 l = VectorDistance2(v1, v2);
4352 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4354 l += (1.0f / 1024.0f);
4355 if (shortest[0].length2 > l || i == 0)
4357 shortest[1] = shortest[0];
4358 shortest[0].length2 = l;
4359 shortest[0].v1 = v1;
4360 shortest[0].v2 = v2;
4362 else if (shortest[1].length2 > l || i == 1)
4364 shortest[1].length2 = l;
4365 shortest[1].v1 = v1;
4366 shortest[1].v2 = v2;
4369 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4370 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4372 Debug_PolygonBegin(NULL, 0, false, 0);
4373 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4374 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);
4375 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4378 // this calculates the right vector from the shortest edge
4379 // and the up vector from the edge midpoints
4380 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4381 VectorNormalize(right);
4382 VectorSubtract(end, start, up);
4383 VectorNormalize(up);
4384 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4385 //VectorSubtract(rsurface.modelorg, center, forward);
4386 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4387 VectorNegate(forward, forward);
4388 VectorReflect(forward, 0, up, forward);
4389 VectorNormalize(forward);
4390 CrossProduct(up, forward, newright);
4391 VectorNormalize(newright);
4393 Debug_PolygonBegin(NULL, 0, false, 0);
4394 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);
4395 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4396 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4400 Debug_PolygonBegin(NULL, 0, false, 0);
4401 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4402 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[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);
4406 // rotate the quad around the up axis vector, this is made
4407 // especially easy by the fact we know the quad is flat,
4408 // so we only have to subtract the center position and
4409 // measure distance along the right vector, and then
4410 // multiply that by the newright vector and add back the
4412 // we also need to subtract the old position to undo the
4413 // displacement from the center, which we do with a
4414 // DotProduct, the subtraction/addition of center is also
4415 // optimized into DotProducts here
4416 l = DotProduct(right, center);
4417 for (i = 0;i < 4;i++)
4419 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4420 f = DotProduct(right, v1) - l;
4421 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4424 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);
4425 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);
4427 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4428 rsurface.vertex3f_bufferobject = 0;
4429 rsurface.vertex3f_bufferoffset = 0;
4430 rsurface.svector3f = rsurface.array_deformedsvector3f;
4431 rsurface.svector3f_bufferobject = 0;
4432 rsurface.svector3f_bufferoffset = 0;
4433 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4434 rsurface.tvector3f_bufferobject = 0;
4435 rsurface.tvector3f_bufferoffset = 0;
4436 rsurface.normal3f = rsurface.array_deformednormal3f;
4437 rsurface.normal3f_bufferobject = 0;
4438 rsurface.normal3f_bufferoffset = 0;
4440 case Q3DEFORM_NORMAL:
4441 // deform the normals to make reflections wavey
4442 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4444 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4445 for (j = 0;j < surface->num_vertices;j++)
4448 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4449 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4450 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4451 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4452 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4453 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4454 VectorNormalize(normal);
4456 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);
4458 rsurface.svector3f = rsurface.array_deformedsvector3f;
4459 rsurface.svector3f_bufferobject = 0;
4460 rsurface.svector3f_bufferoffset = 0;
4461 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4462 rsurface.tvector3f_bufferobject = 0;
4463 rsurface.tvector3f_bufferoffset = 0;
4464 rsurface.normal3f = rsurface.array_deformednormal3f;
4465 rsurface.normal3f_bufferobject = 0;
4466 rsurface.normal3f_bufferoffset = 0;
4469 // deform vertex array to make wavey water and flags and such
4470 waveparms[0] = deform->waveparms[0];
4471 waveparms[1] = deform->waveparms[1];
4472 waveparms[2] = deform->waveparms[2];
4473 waveparms[3] = deform->waveparms[3];
4474 // this is how a divisor of vertex influence on deformation
4475 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4476 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4477 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4479 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4480 for (j = 0;j < surface->num_vertices;j++)
4482 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4483 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4484 // if the wavefunc depends on time, evaluate it per-vertex
4487 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4488 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4490 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4493 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4494 rsurface.vertex3f_bufferobject = 0;
4495 rsurface.vertex3f_bufferoffset = 0;
4497 case Q3DEFORM_BULGE:
4498 // deform vertex array to make the surface have moving bulges
4499 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4501 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4502 for (j = 0;j < surface->num_vertices;j++)
4504 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4505 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4508 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4509 rsurface.vertex3f_bufferobject = 0;
4510 rsurface.vertex3f_bufferoffset = 0;
4513 // deform vertex array
4514 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4515 VectorScale(deform->parms, scale, waveparms);
4516 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4518 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4519 for (j = 0;j < surface->num_vertices;j++)
4520 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4522 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4523 rsurface.vertex3f_bufferobject = 0;
4524 rsurface.vertex3f_bufferoffset = 0;
4528 // generate texcoords based on the chosen texcoord source
4529 switch(rsurface.texture->tcgen.tcgen)
4532 case Q3TCGEN_TEXTURE:
4533 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4534 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4535 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4537 case Q3TCGEN_LIGHTMAP:
4538 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4539 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4540 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4542 case Q3TCGEN_VECTOR:
4543 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4545 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4546 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)
4548 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4549 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4552 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4553 rsurface.texcoordtexture2f_bufferobject = 0;
4554 rsurface.texcoordtexture2f_bufferoffset = 0;
4556 case Q3TCGEN_ENVIRONMENT:
4557 // make environment reflections using a spheremap
4558 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4560 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4561 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4562 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4563 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4564 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4566 float l, d, eyedir[3];
4567 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4568 l = 0.5f / VectorLength(eyedir);
4569 d = DotProduct(normal, eyedir)*2;
4570 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4571 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4574 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4575 rsurface.texcoordtexture2f_bufferobject = 0;
4576 rsurface.texcoordtexture2f_bufferoffset = 0;
4579 // the only tcmod that needs software vertex processing is turbulent, so
4580 // check for it here and apply the changes if needed
4581 // and we only support that as the first one
4582 // (handling a mixture of turbulent and other tcmods would be problematic
4583 // without punting it entirely to a software path)
4584 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4586 amplitude = rsurface.texture->tcmods[0].parms[1];
4587 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4588 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4590 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4591 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)
4593 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4594 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4597 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4598 rsurface.texcoordtexture2f_bufferobject = 0;
4599 rsurface.texcoordtexture2f_bufferoffset = 0;
4601 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4602 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4603 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4604 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4607 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4610 const msurface_t *surface = texturesurfacelist[0];
4611 const msurface_t *surface2;
4616 // TODO: lock all array ranges before render, rather than on each surface
4617 if (texturenumsurfaces == 1)
4619 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4620 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));
4622 else if (r_batchmode.integer == 2)
4624 #define MAXBATCHTRIANGLES 4096
4625 int batchtriangles = 0;
4626 int batchelements[MAXBATCHTRIANGLES*3];
4627 for (i = 0;i < texturenumsurfaces;i = j)
4629 surface = texturesurfacelist[i];
4631 if (surface->num_triangles > MAXBATCHTRIANGLES)
4633 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));
4636 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4637 batchtriangles = surface->num_triangles;
4638 firstvertex = surface->num_firstvertex;
4639 endvertex = surface->num_firstvertex + surface->num_vertices;
4640 for (;j < texturenumsurfaces;j++)
4642 surface2 = texturesurfacelist[j];
4643 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4645 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4646 batchtriangles += surface2->num_triangles;
4647 firstvertex = min(firstvertex, surface2->num_firstvertex);
4648 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4650 surface2 = texturesurfacelist[j-1];
4651 numvertices = endvertex - firstvertex;
4652 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4655 else if (r_batchmode.integer == 1)
4657 for (i = 0;i < texturenumsurfaces;i = j)
4659 surface = texturesurfacelist[i];
4660 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4661 if (texturesurfacelist[j] != surface2)
4663 surface2 = texturesurfacelist[j-1];
4664 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4665 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4666 GL_LockArrays(surface->num_firstvertex, numvertices);
4667 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4672 for (i = 0;i < texturenumsurfaces;i++)
4674 surface = texturesurfacelist[i];
4675 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4676 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));
4681 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4683 int i, planeindex, vertexindex;
4687 r_waterstate_waterplane_t *p, *bestp;
4688 msurface_t *surface;
4689 if (r_waterstate.renderingscene)
4691 for (i = 0;i < texturenumsurfaces;i++)
4693 surface = texturesurfacelist[i];
4694 if (lightmaptexunit >= 0)
4695 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4696 if (deluxemaptexunit >= 0)
4697 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4698 // pick the closest matching water plane
4701 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4704 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4706 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4707 d += fabs(PlaneDiff(vert, &p->plane));
4709 if (bestd > d || !bestp)
4717 if (refractiontexunit >= 0)
4718 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4719 if (reflectiontexunit >= 0)
4720 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4724 if (refractiontexunit >= 0)
4725 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4726 if (reflectiontexunit >= 0)
4727 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4729 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4730 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));
4734 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4738 const msurface_t *surface = texturesurfacelist[0];
4739 const msurface_t *surface2;
4744 // TODO: lock all array ranges before render, rather than on each surface
4745 if (texturenumsurfaces == 1)
4747 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4748 if (deluxemaptexunit >= 0)
4749 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4750 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4751 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4753 else if (r_batchmode.integer == 2)
4755 #define MAXBATCHTRIANGLES 4096
4756 int batchtriangles = 0;
4757 int batchelements[MAXBATCHTRIANGLES*3];
4758 for (i = 0;i < texturenumsurfaces;i = j)
4760 surface = texturesurfacelist[i];
4761 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4762 if (deluxemaptexunit >= 0)
4763 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4765 if (surface->num_triangles > MAXBATCHTRIANGLES)
4767 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));
4770 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4771 batchtriangles = surface->num_triangles;
4772 firstvertex = surface->num_firstvertex;
4773 endvertex = surface->num_firstvertex + surface->num_vertices;
4774 for (;j < texturenumsurfaces;j++)
4776 surface2 = texturesurfacelist[j];
4777 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4779 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4780 batchtriangles += surface2->num_triangles;
4781 firstvertex = min(firstvertex, surface2->num_firstvertex);
4782 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4784 surface2 = texturesurfacelist[j-1];
4785 numvertices = endvertex - firstvertex;
4786 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4789 else if (r_batchmode.integer == 1)
4792 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4793 for (i = 0;i < texturenumsurfaces;i = j)
4795 surface = texturesurfacelist[i];
4796 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4797 if (texturesurfacelist[j] != surface2)
4799 Con_Printf(" %i", j - i);
4802 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4804 for (i = 0;i < texturenumsurfaces;i = j)
4806 surface = texturesurfacelist[i];
4807 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4808 if (deluxemaptexunit >= 0)
4809 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4810 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4811 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4814 Con_Printf(" %i", j - i);
4816 surface2 = texturesurfacelist[j-1];
4817 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4818 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4819 GL_LockArrays(surface->num_firstvertex, numvertices);
4820 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4828 for (i = 0;i < texturenumsurfaces;i++)
4830 surface = texturesurfacelist[i];
4831 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4832 if (deluxemaptexunit >= 0)
4833 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4834 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4835 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4840 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4843 int texturesurfaceindex;
4844 if (r_showsurfaces.integer == 2)
4846 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4848 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4849 for (j = 0;j < surface->num_triangles;j++)
4851 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4852 GL_Color(f, f, f, 1);
4853 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)));
4859 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4861 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4862 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4863 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);
4864 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4865 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4870 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4872 int texturesurfaceindex;
4876 if (rsurface.lightmapcolor4f)
4878 // generate color arrays for the surfaces in this list
4879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4881 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4882 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)
4884 f = FogPoint_Model(v);
4894 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4896 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4897 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)
4899 f = FogPoint_Model(v);
4907 rsurface.lightmapcolor4f = rsurface.array_color4f;
4908 rsurface.lightmapcolor4f_bufferobject = 0;
4909 rsurface.lightmapcolor4f_bufferoffset = 0;
4912 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4914 int texturesurfaceindex;
4917 if (!rsurface.lightmapcolor4f)
4919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4921 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4922 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)
4930 rsurface.lightmapcolor4f = rsurface.array_color4f;
4931 rsurface.lightmapcolor4f_bufferobject = 0;
4932 rsurface.lightmapcolor4f_bufferoffset = 0;
4935 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4938 rsurface.lightmapcolor4f = NULL;
4939 rsurface.lightmapcolor4f_bufferobject = 0;
4940 rsurface.lightmapcolor4f_bufferoffset = 0;
4941 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4942 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4943 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4944 GL_Color(r, g, b, a);
4945 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
4948 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4950 // TODO: optimize applyfog && applycolor case
4951 // just apply fog if necessary, and tint the fog color array if necessary
4952 rsurface.lightmapcolor4f = NULL;
4953 rsurface.lightmapcolor4f_bufferobject = 0;
4954 rsurface.lightmapcolor4f_bufferoffset = 0;
4955 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
4956 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
4957 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
4958 GL_Color(r, g, b, a);
4959 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4962 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
4964 int texturesurfaceindex;
4968 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
4970 // generate color arrays for the surfaces in this list
4971 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4973 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4974 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
4976 if (surface->lightmapinfo->samples)
4978 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
4979 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
4980 VectorScale(lm, scale, c);
4981 if (surface->lightmapinfo->styles[1] != 255)
4983 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
4985 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
4986 VectorMA(c, scale, lm, c);
4987 if (surface->lightmapinfo->styles[2] != 255)
4990 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
4991 VectorMA(c, scale, lm, c);
4992 if (surface->lightmapinfo->styles[3] != 255)
4995 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
4996 VectorMA(c, scale, lm, c);
5006 rsurface.lightmapcolor4f = rsurface.array_color4f;
5007 rsurface.lightmapcolor4f_bufferobject = 0;
5008 rsurface.lightmapcolor4f_bufferoffset = 0;
5012 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5013 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5014 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5016 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5017 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5018 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5019 GL_Color(r, g, b, a);
5020 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5023 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5025 int texturesurfaceindex;
5029 vec3_t ambientcolor;
5030 vec3_t diffusecolor;
5034 VectorCopy(rsurface.modellight_lightdir, lightdir);
5035 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5036 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5037 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5038 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5039 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5040 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5041 if (VectorLength2(diffusecolor) > 0)
5043 // generate color arrays for the surfaces in this list
5044 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5046 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5047 int numverts = surface->num_vertices;
5048 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5049 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5050 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5051 // q3-style directional shading
5052 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5054 if ((f = DotProduct(c2, lightdir)) > 0)
5055 VectorMA(ambientcolor, f, diffusecolor, c);
5057 VectorCopy(ambientcolor, c);
5066 rsurface.lightmapcolor4f = rsurface.array_color4f;
5067 rsurface.lightmapcolor4f_bufferobject = 0;
5068 rsurface.lightmapcolor4f_bufferoffset = 0;
5072 r = ambientcolor[0];
5073 g = ambientcolor[1];
5074 b = ambientcolor[2];
5075 rsurface.lightmapcolor4f = NULL;
5076 rsurface.lightmapcolor4f_bufferobject = 0;
5077 rsurface.lightmapcolor4f_bufferoffset = 0;
5079 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5080 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5081 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5082 GL_Color(r, g, b, a);
5083 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5086 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5088 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5089 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5090 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5091 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5092 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5094 rsurface.mode = RSURFMODE_SHOWSURFACES;
5096 GL_BlendFunc(GL_ONE, GL_ZERO);
5097 R_Mesh_ColorPointer(NULL, 0, 0);
5098 R_Mesh_ResetTextureState();
5100 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5101 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5104 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5106 // transparent sky would be ridiculous
5107 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5109 if (rsurface.mode != RSURFMODE_SKY)
5111 if (rsurface.mode == RSURFMODE_GLSL)
5113 qglUseProgramObjectARB(0);CHECKGLERROR
5115 rsurface.mode = RSURFMODE_SKY;
5119 skyrendernow = false;
5121 // restore entity matrix
5122 R_Mesh_Matrix(&rsurface.matrix);
5124 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5125 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5126 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5127 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5129 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5130 // skymasking on them, and Quake3 never did sky masking (unlike
5131 // software Quake and software Quake2), so disable the sky masking
5132 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5133 // and skymasking also looks very bad when noclipping outside the
5134 // level, so don't use it then either.
5135 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5137 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5138 R_Mesh_ColorPointer(NULL, 0, 0);
5139 R_Mesh_ResetTextureState();
5140 if (skyrendermasked)
5142 // depth-only (masking)
5143 GL_ColorMask(0,0,0,0);
5144 // just to make sure that braindead drivers don't draw
5145 // anything despite that colormask...
5146 GL_BlendFunc(GL_ZERO, GL_ONE);
5151 GL_BlendFunc(GL_ONE, GL_ZERO);
5153 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5154 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5155 if (skyrendermasked)
5156 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5160 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5162 if (rsurface.mode != RSURFMODE_GLSL)
5164 rsurface.mode = RSURFMODE_GLSL;
5165 R_Mesh_ResetTextureState();
5168 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5169 if (!r_glsl_permutation)
5172 if (rsurface.lightmode == 2)
5173 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5175 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5176 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5177 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5178 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5179 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5180 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5182 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]);
5183 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5185 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5186 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5187 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5188 R_Mesh_ColorPointer(NULL, 0, 0);
5190 else if (rsurface.uselightmaptexture)
5192 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5193 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5194 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5195 R_Mesh_ColorPointer(NULL, 0, 0);
5199 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5200 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5201 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5202 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5205 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5207 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5208 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5209 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5210 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5212 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5217 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5219 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5221 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5223 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5228 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5230 // OpenGL 1.3 path - anything not completely ancient
5231 int texturesurfaceindex;
5232 qboolean applycolor;
5236 const texturelayer_t *layer;
5237 if (rsurface.mode != RSURFMODE_MULTIPASS)
5238 rsurface.mode = RSURFMODE_MULTIPASS;
5239 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5240 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5243 int layertexrgbscale;
5244 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5246 if (layerindex == 0)
5250 GL_AlphaTest(false);
5251 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5254 GL_DepthMask(layer->depthmask);
5255 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5256 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5258 layertexrgbscale = 4;
5259 VectorScale(layer->color, 0.25f, layercolor);
5261 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5263 layertexrgbscale = 2;
5264 VectorScale(layer->color, 0.5f, layercolor);
5268 layertexrgbscale = 1;
5269 VectorScale(layer->color, 1.0f, layercolor);
5271 layercolor[3] = layer->color[3];
5272 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5273 R_Mesh_ColorPointer(NULL, 0, 0);
5274 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5275 switch (layer->type)
5277 case TEXTURELAYERTYPE_LITTEXTURE:
5278 memset(&m, 0, sizeof(m));
5279 m.tex[0] = R_GetTexture(r_texture_white);
5280 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5281 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5282 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5283 m.tex[1] = R_GetTexture(layer->texture);
5284 m.texmatrix[1] = layer->texmatrix;
5285 m.texrgbscale[1] = layertexrgbscale;
5286 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5287 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5288 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5289 R_Mesh_TextureState(&m);
5290 if (rsurface.lightmode == 2)
5291 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5292 else if (rsurface.uselightmaptexture)
5293 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5295 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5297 case TEXTURELAYERTYPE_TEXTURE:
5298 memset(&m, 0, sizeof(m));
5299 m.tex[0] = R_GetTexture(layer->texture);
5300 m.texmatrix[0] = layer->texmatrix;
5301 m.texrgbscale[0] = layertexrgbscale;
5302 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5303 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5304 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5305 R_Mesh_TextureState(&m);
5306 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5308 case TEXTURELAYERTYPE_FOG:
5309 memset(&m, 0, sizeof(m));
5310 m.texrgbscale[0] = layertexrgbscale;
5313 m.tex[0] = R_GetTexture(layer->texture);
5314 m.texmatrix[0] = layer->texmatrix;
5315 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5316 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5317 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5319 R_Mesh_TextureState(&m);
5320 // generate a color array for the fog pass
5321 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5322 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5326 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5327 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)
5329 f = 1 - FogPoint_Model(v);
5330 c[0] = layercolor[0];
5331 c[1] = layercolor[1];
5332 c[2] = layercolor[2];
5333 c[3] = f * layercolor[3];
5336 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5339 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5341 GL_LockArrays(0, 0);
5344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5346 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5347 GL_AlphaTest(false);
5351 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5353 // OpenGL 1.1 - crusty old voodoo path
5354 int texturesurfaceindex;
5358 const texturelayer_t *layer;
5359 if (rsurface.mode != RSURFMODE_MULTIPASS)
5360 rsurface.mode = RSURFMODE_MULTIPASS;
5361 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5362 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5364 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5366 if (layerindex == 0)
5370 GL_AlphaTest(false);
5371 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5374 GL_DepthMask(layer->depthmask);
5375 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5376 R_Mesh_ColorPointer(NULL, 0, 0);
5377 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5378 switch (layer->type)
5380 case TEXTURELAYERTYPE_LITTEXTURE:
5381 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5383 // two-pass lit texture with 2x rgbscale
5384 // first the lightmap pass
5385 memset(&m, 0, sizeof(m));
5386 m.tex[0] = R_GetTexture(r_texture_white);
5387 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5388 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5389 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5390 R_Mesh_TextureState(&m);
5391 if (rsurface.lightmode == 2)
5392 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5393 else if (rsurface.uselightmaptexture)
5394 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5396 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5397 GL_LockArrays(0, 0);
5398 // then apply the texture to it
5399 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5400 memset(&m, 0, sizeof(m));
5401 m.tex[0] = R_GetTexture(layer->texture);
5402 m.texmatrix[0] = layer->texmatrix;
5403 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5404 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5405 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5406 R_Mesh_TextureState(&m);
5407 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);
5411 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5412 memset(&m, 0, sizeof(m));
5413 m.tex[0] = R_GetTexture(layer->texture);
5414 m.texmatrix[0] = layer->texmatrix;
5415 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5416 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5417 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5418 R_Mesh_TextureState(&m);
5419 if (rsurface.lightmode == 2)
5420 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);
5422 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);
5425 case TEXTURELAYERTYPE_TEXTURE:
5426 // singletexture unlit texture with transparency support
5427 memset(&m, 0, sizeof(m));
5428 m.tex[0] = R_GetTexture(layer->texture);
5429 m.texmatrix[0] = layer->texmatrix;
5430 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5431 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5432 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5433 R_Mesh_TextureState(&m);
5434 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);
5436 case TEXTURELAYERTYPE_FOG:
5437 // singletexture fogging
5438 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5441 memset(&m, 0, sizeof(m));
5442 m.tex[0] = R_GetTexture(layer->texture);
5443 m.texmatrix[0] = layer->texmatrix;
5444 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5445 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5446 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5447 R_Mesh_TextureState(&m);
5450 R_Mesh_ResetTextureState();
5451 // generate a color array for the fog pass
5452 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5456 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5457 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)
5459 f = 1 - FogPoint_Model(v);
5460 c[0] = layer->color[0];
5461 c[1] = layer->color[1];
5462 c[2] = layer->color[2];
5463 c[3] = f * layer->color[3];
5466 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5469 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5471 GL_LockArrays(0, 0);
5474 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5476 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5477 GL_AlphaTest(false);
5481 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5483 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5485 rsurface.rtlight = NULL;
5489 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5491 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5493 if (rsurface.mode != RSURFMODE_MULTIPASS)
5494 rsurface.mode = RSURFMODE_MULTIPASS;
5495 if (r_depthfirst.integer == 3)
5497 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5498 if (!r_view.showdebug)
5499 GL_Color(0, 0, 0, 1);
5501 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5505 GL_ColorMask(0,0,0,0);
5508 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5509 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5510 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5512 GL_BlendFunc(GL_ONE, GL_ZERO);
5514 GL_AlphaTest(false);
5515 R_Mesh_ColorPointer(NULL, 0, 0);
5516 R_Mesh_ResetTextureState();
5517 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5518 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5519 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5520 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5522 else if (r_depthfirst.integer == 3)
5524 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5526 GL_Color(0, 0, 0, 1);
5527 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5529 else if (r_showsurfaces.integer)
5531 if (rsurface.mode != RSURFMODE_MULTIPASS)
5532 rsurface.mode = RSURFMODE_MULTIPASS;
5533 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5534 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5536 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5537 GL_BlendFunc(GL_ONE, GL_ZERO);
5538 GL_DepthMask(writedepth);
5540 GL_AlphaTest(false);
5541 R_Mesh_ColorPointer(NULL, 0, 0);
5542 R_Mesh_ResetTextureState();
5543 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5544 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5545 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5547 else if (gl_lightmaps.integer)
5550 if (rsurface.mode != RSURFMODE_MULTIPASS)
5551 rsurface.mode = RSURFMODE_MULTIPASS;
5552 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5554 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5555 GL_BlendFunc(GL_ONE, GL_ZERO);
5556 GL_DepthMask(writedepth);
5558 GL_AlphaTest(false);
5559 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5560 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5561 R_Mesh_ColorPointer(NULL, 0, 0);
5562 memset(&m, 0, sizeof(m));
5563 m.tex[0] = R_GetTexture(r_texture_white);
5564 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5565 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5566 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5567 R_Mesh_TextureState(&m);
5568 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5569 if (rsurface.lightmode == 2)
5570 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5571 else if (rsurface.uselightmaptexture)
5572 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5574 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5575 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5577 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5579 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5580 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5582 else if (rsurface.texture->currentnumlayers)
5584 // write depth for anything we skipped on the depth-only pass earlier
5585 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5587 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5588 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5589 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5590 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5591 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5592 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5593 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5594 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5595 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5596 if (r_glsl.integer && gl_support_fragment_shader)
5597 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5598 else if (gl_combine.integer && r_textureunits.integer >= 2)
5599 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5601 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5602 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5605 GL_LockArrays(0, 0);
5608 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5611 int texturenumsurfaces, endsurface;
5613 msurface_t *surface;
5614 msurface_t *texturesurfacelist[1024];
5616 // if the model is static it doesn't matter what value we give for
5617 // wantnormals and wanttangents, so this logic uses only rules applicable
5618 // to a model, knowing that they are meaningless otherwise
5619 if (ent == r_refdef.worldentity)
5620 RSurf_ActiveWorldEntity();
5621 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5622 RSurf_ActiveModelEntity(ent, false, false);
5624 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5626 for (i = 0;i < numsurfaces;i = j)
5629 surface = rsurface.modelsurfaces + surfacelist[i];
5630 texture = surface->texture;
5631 R_UpdateTextureInfo(ent, texture);
5632 rsurface.texture = texture->currentframe;
5633 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5634 // scan ahead until we find a different texture
5635 endsurface = min(i + 1024, numsurfaces);
5636 texturenumsurfaces = 0;
5637 texturesurfacelist[texturenumsurfaces++] = surface;
5638 for (;j < endsurface;j++)
5640 surface = rsurface.modelsurfaces + surfacelist[j];
5641 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5643 texturesurfacelist[texturenumsurfaces++] = surface;
5645 // render the range of surfaces
5646 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5652 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5655 vec3_t tempcenter, center;
5657 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5660 for (i = 0;i < numsurfaces;i++)
5661 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5662 R_Water_AddWaterPlane(surfacelist[i]);
5665 // break the surface list down into batches by texture and use of lightmapping
5666 for (i = 0;i < numsurfaces;i = j)
5669 // texture is the base texture pointer, rsurface.texture is the
5670 // current frame/skin the texture is directing us to use (for example
5671 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5672 // use skin 1 instead)
5673 texture = surfacelist[i]->texture;
5674 rsurface.texture = texture->currentframe;
5675 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5676 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5678 // if this texture is not the kind we want, skip ahead to the next one
5679 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5683 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5685 // transparent surfaces get pushed off into the transparent queue
5686 const msurface_t *surface = surfacelist[i];
5689 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5690 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5691 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5692 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5693 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5697 // simply scan ahead until we find a different texture or lightmap state
5698 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5700 // render the range of surfaces
5701 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5706 float locboxvertex3f[6*4*3] =
5708 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5709 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5710 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5711 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5712 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5713 1,0,0, 0,0,0, 0,1,0, 1,1,0
5716 int locboxelement3i[6*2*3] =
5726 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5729 cl_locnode_t *loc = (cl_locnode_t *)ent;
5731 float vertex3f[6*4*3];
5733 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5734 GL_DepthMask(false);
5735 GL_DepthRange(0, 1);
5736 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5738 GL_CullFace(GL_NONE);
5739 R_Mesh_Matrix(&identitymatrix);
5741 R_Mesh_VertexPointer(vertex3f, 0, 0);
5742 R_Mesh_ColorPointer(NULL, 0, 0);
5743 R_Mesh_ResetTextureState();
5746 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5747 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5748 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5749 surfacelist[0] < 0 ? 0.5f : 0.125f);
5751 if (VectorCompare(loc->mins, loc->maxs))
5753 VectorSet(size, 2, 2, 2);
5754 VectorMA(loc->mins, -0.5f, size, mins);
5758 VectorCopy(loc->mins, mins);
5759 VectorSubtract(loc->maxs, loc->mins, size);
5762 for (i = 0;i < 6*4*3;)
5763 for (j = 0;j < 3;j++, i++)
5764 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5766 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5769 void R_DrawLocs(void)
5772 cl_locnode_t *loc, *nearestloc;
5774 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5775 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5777 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5778 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5782 void R_DrawCollisionBrushes(entity_render_t *ent)
5786 msurface_t *surface;
5787 model_t *model = ent->model;
5788 if (!model->brush.num_brushes)
5791 R_Mesh_ColorPointer(NULL, 0, 0);
5792 R_Mesh_ResetTextureState();
5793 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5794 GL_DepthMask(false);
5795 GL_DepthRange(0, 1);
5796 GL_DepthTest(!r_showdisabledepthtest.integer);
5797 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5798 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5799 if (brush->colbrushf && brush->colbrushf->numtriangles)
5800 R_DrawCollisionBrush(brush->colbrushf);
5801 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5802 if (surface->num_collisiontriangles)
5803 R_DrawCollisionSurface(ent, surface);
5804 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5807 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5810 const int *elements;
5811 msurface_t *surface;
5812 model_t *model = ent->model;
5815 GL_DepthRange(0, 1);
5816 GL_DepthTest(!r_showdisabledepthtest.integer);
5817 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5819 GL_BlendFunc(GL_ONE, GL_ZERO);
5820 R_Mesh_ColorPointer(NULL, 0, 0);
5821 R_Mesh_ResetTextureState();
5822 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5824 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5826 rsurface.texture = surface->texture->currentframe;
5827 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5829 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5832 if (!rsurface.texture->currentlayers->depthmask)
5833 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5834 else if (ent == r_refdef.worldentity)
5835 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5837 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5838 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5841 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5843 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5844 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5845 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5846 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5853 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5855 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5857 VectorCopy(rsurface.vertex3f + l * 3, v);
5858 qglVertex3f(v[0], v[1], v[2]);
5859 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5860 qglVertex3f(v[0], v[1], v[2]);
5864 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5866 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5868 VectorCopy(rsurface.vertex3f + l * 3, v);
5869 qglVertex3f(v[0], v[1], v[2]);
5870 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5871 qglVertex3f(v[0], v[1], v[2]);
5875 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5877 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5879 VectorCopy(rsurface.vertex3f + l * 3, v);
5880 qglVertex3f(v[0], v[1], v[2]);
5881 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5882 qglVertex3f(v[0], v[1], v[2]);
5889 rsurface.texture = NULL;
5892 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5893 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5895 int i, j, endj, f, flagsmask;
5896 int counttriangles = 0;
5897 msurface_t *surface, **surfacechain;
5899 model_t *model = r_refdef.worldmodel;
5900 const int maxsurfacelist = 1024;
5901 int numsurfacelist = 0;
5902 msurface_t *surfacelist[1024];
5906 RSurf_ActiveWorldEntity();
5908 // update light styles
5909 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5911 for (i = 0;i < model->brushq1.light_styles;i++)
5913 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5915 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5916 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5917 for (;(surface = *surfacechain);surfacechain++)
5918 surface->cached_dlight = true;
5923 R_UpdateAllTextureInfo(r_refdef.worldentity);
5924 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
5927 rsurface.uselightmaptexture = false;
5928 rsurface.texture = NULL;
5930 j = model->firstmodelsurface;
5931 endj = j + model->nummodelsurfaces;
5934 // quickly skip over non-visible surfaces
5935 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
5937 // quickly iterate over visible surfaces
5938 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
5940 // process this surface
5941 surface = model->data_surfaces + j;
5942 // if this surface fits the criteria, add it to the list
5943 if (surface->num_triangles)
5945 // if lightmap parameters changed, rebuild lightmap texture
5946 if (surface->cached_dlight)
5947 R_BuildLightMap(r_refdef.worldentity, surface);
5948 // add face to draw list
5949 surfacelist[numsurfacelist++] = surface;
5950 counttriangles += surface->num_triangles;
5951 if (numsurfacelist >= maxsurfacelist)
5953 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5960 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
5961 r_refdef.stats.entities_triangles += counttriangles;
5964 if (r_view.showdebug)
5966 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
5967 R_DrawCollisionBrushes(r_refdef.worldentity);
5969 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
5970 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
5974 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5976 int i, f, flagsmask;
5977 int counttriangles = 0;
5978 msurface_t *surface, *endsurface, **surfacechain;
5980 model_t *model = ent->model;
5981 const int maxsurfacelist = 1024;
5982 int numsurfacelist = 0;
5983 msurface_t *surfacelist[1024];
5987 // if the model is static it doesn't matter what value we give for
5988 // wantnormals and wanttangents, so this logic uses only rules applicable
5989 // to a model, knowing that they are meaningless otherwise
5990 if (ent == r_refdef.worldentity)
5991 RSurf_ActiveWorldEntity();
5992 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5993 RSurf_ActiveModelEntity(ent, false, false);
5995 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
5997 // update light styles
5998 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6000 for (i = 0;i < model->brushq1.light_styles;i++)
6002 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6004 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6005 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6006 for (;(surface = *surfacechain);surfacechain++)
6007 surface->cached_dlight = true;
6012 R_UpdateAllTextureInfo(ent);
6013 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6016 rsurface.uselightmaptexture = false;
6017 rsurface.texture = NULL;
6019 surface = model->data_surfaces + model->firstmodelsurface;
6020 endsurface = surface + model->nummodelsurfaces;
6021 for (;surface < endsurface;surface++)
6023 // if this surface fits the criteria, add it to the list
6024 if (surface->num_triangles)
6026 // if lightmap parameters changed, rebuild lightmap texture
6027 if (surface->cached_dlight)
6028 R_BuildLightMap(ent, surface);
6029 // add face to draw list
6030 surfacelist[numsurfacelist++] = surface;
6031 counttriangles += surface->num_triangles;
6032 if (numsurfacelist >= maxsurfacelist)
6034 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6040 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6041 r_refdef.stats.entities_triangles += counttriangles;
6044 if (r_view.showdebug)
6046 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
6047 R_DrawCollisionBrushes(ent);
6049 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
6050 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);