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.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
36 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"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 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"};
64 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"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
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)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 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)"};
80 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)"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 cvar_t r_glsl_postprocess_contrastboost = {CVAR_SAVE, "r_glsl_postprocess_contrastboost", "1", "brightening effect (1 is no change, higher values brighten the view)"};
86 cvar_t r_glsl_postprocess_gamma = {CVAR_SAVE, "r_glsl_postprocess_gamma", "1", "inverse gamma correction value, a brightness effect that does not affect white or black, and tends to make the image grey and dull"};
87 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
88 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
89 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
90 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
91 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
93 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
94 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
95 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
96 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
97 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
102 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
104 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
105 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
106 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
107 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
108 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
109 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
110 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
112 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
113 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
114 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
115 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)"};
117 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"};
119 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"};
121 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
123 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
124 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
125 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
126 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
127 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
128 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
130 extern qboolean v_flipped_state;
132 static struct r_bloomstate_s
137 int bloomwidth, bloomheight;
139 int screentexturewidth, screentextureheight;
140 rtexture_t *texture_screen;
142 int bloomtexturewidth, bloomtextureheight;
143 rtexture_t *texture_bloom;
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
158 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
161 r_waterstate_waterplane_t;
163 #define MAX_WATERPLANES 16
165 static struct r_waterstate_s
169 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
171 int waterwidth, waterheight;
172 int texturewidth, textureheight;
174 int maxwaterplanes; // same as MAX_WATERPLANES
176 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
178 float screenscale[2];
179 float screencenter[2];
183 // shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 //rtexture_t *r_texture_fogintensity;
196 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
197 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
199 // vertex coordinates for a quad that covers the screen exactly
200 const static float r_screenvertex3f[12] =
208 extern void R_DrawModelShadows(void);
210 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
213 for (i = 0;i < verts;i++)
224 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
227 for (i = 0;i < verts;i++)
237 // FIXME: move this to client?
240 if (gamemode == GAME_NEHAHRA)
242 Cvar_Set("gl_fogenable", "0");
243 Cvar_Set("gl_fogdensity", "0.2");
244 Cvar_Set("gl_fogred", "0.3");
245 Cvar_Set("gl_foggreen", "0.3");
246 Cvar_Set("gl_fogblue", "0.3");
248 r_refdef.fog_density = 0;
249 r_refdef.fog_red = 0;
250 r_refdef.fog_green = 0;
251 r_refdef.fog_blue = 0;
252 r_refdef.fog_alpha = 1;
253 r_refdef.fog_start = 0;
254 r_refdef.fog_end = 0;
257 float FogForDistance(vec_t dist)
259 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
260 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
263 float FogPoint_World(const vec3_t p)
265 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
268 float FogPoint_Model(const vec3_t p)
270 return FogForDistance(VectorDistance((p), rsurface.modelorg));
273 static void R_BuildBlankTextures(void)
275 unsigned char data[4];
276 data[2] = 128; // normal X
277 data[1] = 128; // normal Y
278 data[0] = 255; // normal Z
279 data[3] = 128; // height
280 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
285 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
298 static void R_BuildNoTexture(void)
301 unsigned char pix[16][16][4];
302 // this makes a light grey/dark grey checkerboard texture
303 for (y = 0;y < 16;y++)
305 for (x = 0;x < 16;x++)
307 if ((y < 8) ^ (x < 8))
323 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
326 static void R_BuildWhiteCube(void)
328 unsigned char data[6*1*1*4];
329 memset(data, 255, sizeof(data));
330 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
333 static void R_BuildNormalizationCube(void)
337 vec_t s, t, intensity;
339 unsigned char data[6][NORMSIZE][NORMSIZE][4];
340 for (side = 0;side < 6;side++)
342 for (y = 0;y < NORMSIZE;y++)
344 for (x = 0;x < NORMSIZE;x++)
346 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
347 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 intensity = 127.0f / sqrt(DotProduct(v, v));
383 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
384 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
385 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
386 data[side][y][x][3] = 255;
390 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
393 static void R_BuildFogTexture(void)
397 unsigned char data1[FOGWIDTH][4];
398 //unsigned char data2[FOGWIDTH][4];
401 r_refdef.fogmasktable_start = r_refdef.fog_start;
402 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
403 r_refdef.fogmasktable_range = r_refdef.fogrange;
404 r_refdef.fogmasktable_density = r_refdef.fog_density;
406 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
407 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
409 d = (x * r - r_refdef.fogmasktable_start);
410 if(developer.integer >= 100)
411 Con_Printf("%f ", d);
413 if (r_fog_exp2.integer)
414 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
416 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
417 if(developer.integer >= 100)
418 Con_Printf(" : %f ", alpha);
419 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
420 if(developer.integer >= 100)
421 Con_Printf(" = %f\n", alpha);
422 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
425 for (x = 0;x < FOGWIDTH;x++)
427 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
432 //data2[x][0] = 255 - b;
433 //data2[x][1] = 255 - b;
434 //data2[x][2] = 255 - b;
437 if (r_texture_fogattenuation)
439 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
440 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
444 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
445 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
449 static const char *builtinshaderstring =
450 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
451 "// written by Forest 'LordHavoc' Hale\n"
453 "// common definitions between vertex shader and fragment shader:\n"
455 "//#ifdef __GLSL_CG_DATA_TYPES\n"
456 "//# define myhalf half\n"
457 "//# define myhalf2 half2\n"
458 "//# define myhalf3 half3\n"
459 "//# define myhalf4 half4\n"
461 "# define myhalf float\n"
462 "# define myhalf2 vec2\n"
463 "# define myhalf3 vec3\n"
464 "# define myhalf4 vec4\n"
467 "#ifdef MODE_DEPTH_OR_SHADOW\n"
469 "# ifdef VERTEX_SHADER\n"
472 " gl_Position = ftransform();\n"
478 "#ifdef MODE_POSTPROCESS\n"
479 "# ifdef VERTEX_SHADER\n"
482 " gl_FrontColor = gl_Color;\n"
483 " gl_Position = ftransform();\n"
484 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
486 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
490 "# ifdef FRAGMENT_SHADER\n"
492 "uniform sampler2D Texture_First;\n"
494 "uniform sampler2D Texture_Second;\n"
496 "#ifdef USEVERTEXTEXTUREBLEND\n"
497 "uniform vec4 TintColor;\n"
499 "#ifdef USECOLORMOD\n"
500 "uniform vec3 Gamma;\n"
502 "#ifdef USECONTRASTBOOST\n"
503 "uniform float ContrastBoostCoeff;\n"
506 "uniform float GammaCoeff;\n"
508 "uniform vec4 UserVec1;\n"
509 "uniform vec4 UserVec2;\n"
510 "uniform vec4 UserVec3;\n"
511 "uniform vec4 UserVec4;\n"
512 "uniform float ClientTime;\n"
515 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
517 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
519 "#ifdef USECONTRASTBOOST\n"
520 " gl_FragColor.rgb /= (ContrastBoostCoeff * gl_FragColor.rgb + vec3(1.0, 1.0, 1.0));\n"
521 " gl_FragColor.rgb *= (ContrastBoostCoeff + 1.0);\n"
524 " gl_FragColor.rgb = pow(gl_FragColor.rgb, GammaCoeff);\n"
526 "#ifdef USEVERTEXTEXTUREBLEND\n"
527 " gl_FragColor = mix(TintColor, gl_FragColor, TintColor.a);\n"
535 "#ifdef MODE_GENERIC\n"
536 "# ifdef VERTEX_SHADER\n"
539 " gl_FrontColor = gl_Color;\n"
540 "# ifdef USEDIFFUSE\n"
541 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
543 "# ifdef USESPECULAR\n"
544 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
546 " gl_Position = ftransform();\n"
549 "# ifdef FRAGMENT_SHADER\n"
551 "# ifdef USEDIFFUSE\n"
552 "uniform sampler2D Texture_First;\n"
554 "# ifdef USESPECULAR\n"
555 "uniform sampler2D Texture_Second;\n"
560 " gl_FragColor = gl_Color;\n"
561 "# ifdef USEDIFFUSE\n"
562 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
565 "# ifdef USESPECULAR\n"
566 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
568 "# ifdef USECOLORMAPPING\n"
569 " gl_FragColor *= tex2;\n"
572 " gl_FragColor += tex2;\n"
574 "# ifdef USEVERTEXTEXTUREBLEND\n"
575 " gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
580 "#else // !MODE_GENERIC\n"
582 "varying vec2 TexCoord;\n"
583 "varying vec2 TexCoordLightmap;\n"
585 "#ifdef MODE_LIGHTSOURCE\n"
586 "varying vec3 CubeVector;\n"
589 "#ifdef MODE_LIGHTSOURCE\n"
590 "varying vec3 LightVector;\n"
592 "#ifdef MODE_LIGHTDIRECTION\n"
593 "varying vec3 LightVector;\n"
596 "varying vec3 EyeVector;\n"
598 "varying vec3 EyeVectorModelSpace;\n"
601 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
602 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
603 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
605 "#ifdef MODE_WATER\n"
606 "varying vec4 ModelViewProjectionPosition;\n"
607 "#ifdef MODE_REFRACTION\n"
608 "varying vec4 ModelViewProjectionPosition;\n"
610 "# ifdef USEREFLECTION\n"
611 "varying vec4 ModelViewProjectionPosition;\n"
620 "// vertex shader specific:\n"
621 "#ifdef VERTEX_SHADER\n"
623 "uniform vec3 LightPosition;\n"
624 "uniform vec3 EyePosition;\n"
625 "uniform vec3 LightDir;\n"
627 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
631 " gl_FrontColor = gl_Color;\n"
632 " // copy the surface texcoord\n"
633 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
634 "#ifndef MODE_LIGHTSOURCE\n"
635 "# ifndef MODE_LIGHTDIRECTION\n"
636 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
640 "#ifdef MODE_LIGHTSOURCE\n"
641 " // transform vertex position into light attenuation/cubemap space\n"
642 " // (-1 to +1 across the light box)\n"
643 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
645 " // transform unnormalized light direction into tangent space\n"
646 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
647 " // normalize it per pixel)\n"
648 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
649 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
650 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
651 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
654 "#ifdef MODE_LIGHTDIRECTION\n"
655 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
656 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
657 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
660 " // transform unnormalized eye direction into tangent space\n"
662 " vec3 EyeVectorModelSpace;\n"
664 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
665 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
666 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
667 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
669 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
670 " VectorS = gl_MultiTexCoord1.xyz;\n"
671 " VectorT = gl_MultiTexCoord2.xyz;\n"
672 " VectorR = gl_MultiTexCoord3.xyz;\n"
675 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
676 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
677 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
678 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
681 "// transform vertex to camera space, using ftransform to match non-VS\n"
683 " gl_Position = ftransform();\n"
685 "#ifdef MODE_WATER\n"
686 " ModelViewProjectionPosition = gl_Position;\n"
688 "#ifdef MODE_REFRACTION\n"
689 " ModelViewProjectionPosition = gl_Position;\n"
691 "#ifdef USEREFLECTION\n"
692 " ModelViewProjectionPosition = gl_Position;\n"
696 "#endif // VERTEX_SHADER\n"
701 "// fragment shader specific:\n"
702 "#ifdef FRAGMENT_SHADER\n"
704 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
705 "uniform sampler2D Texture_Normal;\n"
706 "uniform sampler2D Texture_Color;\n"
707 "uniform sampler2D Texture_Gloss;\n"
708 "uniform sampler2D Texture_Glow;\n"
709 "uniform sampler2D Texture_SecondaryNormal;\n"
710 "uniform sampler2D Texture_SecondaryColor;\n"
711 "uniform sampler2D Texture_SecondaryGloss;\n"
712 "uniform sampler2D Texture_SecondaryGlow;\n"
713 "uniform sampler2D Texture_Pants;\n"
714 "uniform sampler2D Texture_Shirt;\n"
715 "uniform sampler2D Texture_FogMask;\n"
716 "uniform sampler2D Texture_Lightmap;\n"
717 "uniform sampler2D Texture_Deluxemap;\n"
718 "uniform sampler2D Texture_Refraction;\n"
719 "uniform sampler2D Texture_Reflection;\n"
720 "uniform sampler2D Texture_Attenuation;\n"
721 "uniform samplerCube Texture_Cube;\n"
723 "uniform myhalf3 LightColor;\n"
724 "uniform myhalf3 AmbientColor;\n"
725 "uniform myhalf3 DiffuseColor;\n"
726 "uniform myhalf3 SpecularColor;\n"
727 "uniform myhalf3 Color_Pants;\n"
728 "uniform myhalf3 Color_Shirt;\n"
729 "uniform myhalf3 FogColor;\n"
731 "uniform myhalf4 TintColor;\n"
734 "//#ifdef MODE_WATER\n"
735 "uniform vec4 DistortScaleRefractReflect;\n"
736 "uniform vec4 ScreenScaleRefractReflect;\n"
737 "uniform vec4 ScreenCenterRefractReflect;\n"
738 "uniform myhalf4 RefractColor;\n"
739 "uniform myhalf4 ReflectColor;\n"
740 "uniform myhalf ReflectFactor;\n"
741 "uniform myhalf ReflectOffset;\n"
743 "//# ifdef MODE_REFRACTION\n"
744 "//uniform vec4 DistortScaleRefractReflect;\n"
745 "//uniform vec4 ScreenScaleRefractReflect;\n"
746 "//uniform vec4 ScreenCenterRefractReflect;\n"
747 "//uniform myhalf4 RefractColor;\n"
748 "//# ifdef USEREFLECTION\n"
749 "//uniform myhalf4 ReflectColor;\n"
752 "//# ifdef USEREFLECTION\n"
753 "//uniform vec4 DistortScaleRefractReflect;\n"
754 "//uniform vec4 ScreenScaleRefractReflect;\n"
755 "//uniform vec4 ScreenCenterRefractReflect;\n"
756 "//uniform myhalf4 ReflectColor;\n"
761 "uniform myhalf GlowScale;\n"
762 "uniform myhalf SceneBrightness;\n"
763 "#ifdef USECONTRASTBOOST\n"
764 "uniform myhalf ContrastBoostCoeff;\n"
767 "uniform float OffsetMapping_Scale;\n"
768 "uniform float OffsetMapping_Bias;\n"
769 "uniform float FogRangeRecip;\n"
771 "uniform myhalf AmbientScale;\n"
772 "uniform myhalf DiffuseScale;\n"
773 "uniform myhalf SpecularScale;\n"
774 "uniform myhalf SpecularPower;\n"
776 "#ifdef USEOFFSETMAPPING\n"
777 "vec2 OffsetMapping(vec2 TexCoord)\n"
779 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
780 " // 14 sample relief mapping: linear search and then binary search\n"
781 " // this basically steps forward a small amount repeatedly until it finds\n"
782 " // itself inside solid, then jitters forward and back using decreasing\n"
783 " // amounts to find the impact\n"
784 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
785 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
786 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
787 " vec3 RT = vec3(TexCoord, 1);\n"
788 " OffsetVector *= 0.1;\n"
789 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
790 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
791 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
792 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
793 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
794 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
795 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
796 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
797 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
798 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
799 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
800 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
801 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
802 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
805 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
806 " // this basically moves forward the full distance, and then backs up based\n"
807 " // on height of samples\n"
808 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
809 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
810 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
811 " TexCoord += OffsetVector;\n"
812 " OffsetVector *= 0.333;\n"
813 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
814 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
815 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
816 " return TexCoord;\n"
819 "#endif // USEOFFSETMAPPING\n"
821 "#ifdef MODE_WATER\n"
826 "#ifdef USEOFFSETMAPPING\n"
827 " // apply offsetmapping\n"
828 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
829 "#define TexCoord TexCoordOffset\n"
832 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
833 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
834 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
835 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
836 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
839 "#else // !MODE_WATER\n"
840 "#ifdef MODE_REFRACTION\n"
842 "// refraction pass\n"
845 "#ifdef USEOFFSETMAPPING\n"
846 " // apply offsetmapping\n"
847 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
848 "#define TexCoord TexCoordOffset\n"
851 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
852 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
853 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
854 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
857 "#else // !MODE_REFRACTION\n"
860 "#ifdef USEOFFSETMAPPING\n"
861 " // apply offsetmapping\n"
862 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
863 "#define TexCoord TexCoordOffset\n"
866 " // combine the diffuse textures (base, pants, shirt)\n"
867 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
868 "#ifdef USECOLORMAPPING\n"
869 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
871 "#ifdef USEVERTEXTEXTUREBLEND\n"
872 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
873 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
874 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
875 " color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
876 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
879 "#ifdef USEDIFFUSE\n"
880 " // get the surface normal and the gloss color\n"
881 "# ifdef USEVERTEXTEXTUREBLEND\n"
882 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
883 "# ifdef USESPECULAR\n"
884 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
887 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
888 "# ifdef USESPECULAR\n"
889 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
896 "#ifdef MODE_LIGHTSOURCE\n"
899 " // calculate surface normal, light normal, and specular normal\n"
900 " // compute color intensity for the two textures (colormap and glossmap)\n"
901 " // scale by light color and attenuation as efficiently as possible\n"
902 " // (do as much scalar math as possible rather than vector math)\n"
903 "# ifdef USEDIFFUSE\n"
904 " // get the light normal\n"
905 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
907 "# ifdef USESPECULAR\n"
908 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
910 " // calculate directional shading\n"
911 " color.rgb = 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)) * glosscolor);\n"
913 "# ifdef USEDIFFUSE\n"
914 " // calculate directional shading\n"
915 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
917 " // calculate directionless shading\n"
918 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
922 "# ifdef USECUBEFILTER\n"
923 " // apply light cubemap filter\n"
924 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
925 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
927 "#endif // MODE_LIGHTSOURCE\n"
932 "#ifdef MODE_LIGHTDIRECTION\n"
933 " // directional model lighting\n"
934 "# ifdef USEDIFFUSE\n"
935 " // get the light normal\n"
936 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
938 "# ifdef USESPECULAR\n"
939 " // calculate directional shading\n"
940 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
941 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
942 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
944 "# ifdef USEDIFFUSE\n"
946 " // calculate directional shading\n"
947 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
949 " color.rgb *= AmbientColor;\n"
952 "#endif // MODE_LIGHTDIRECTION\n"
957 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
958 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
960 " // get the light normal\n"
961 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
962 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
963 " // calculate directional shading\n"
964 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
965 "# ifdef USESPECULAR\n"
966 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
967 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
970 " // apply lightmap color\n"
971 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
972 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
977 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
978 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
980 " // get the light normal\n"
981 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
982 " // calculate directional shading\n"
983 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
984 "# ifdef USESPECULAR\n"
985 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
986 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
989 " // apply lightmap color\n"
990 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
991 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
996 "#ifdef MODE_LIGHTMAP\n"
997 " // apply lightmap color\n"
998 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
999 "#endif // MODE_LIGHTMAP\n"
1004 "#ifdef MODE_VERTEXCOLOR\n"
1005 " // apply lightmap color\n"
1006 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1007 "#endif // MODE_VERTEXCOLOR\n"
1012 "#ifdef MODE_FLATCOLOR\n"
1013 "#endif // MODE_FLATCOLOR\n"
1021 " color *= TintColor;\n"
1024 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1027 "#ifdef USECONTRASTBOOST\n"
1028 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1031 " color.rgb *= SceneBrightness;\n"
1033 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1035 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1038 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1039 "#ifdef USEREFLECTION\n"
1040 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1041 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1042 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1043 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1046 " gl_FragColor = vec4(color);\n"
1048 "#endif // !MODE_REFRACTION\n"
1049 "#endif // !MODE_WATER\n"
1051 "#endif // FRAGMENT_SHADER\n"
1053 "#endif // !MODE_GENERIC\n"
1054 "#endif // !MODE_POSTPROCESS\n"
1055 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1058 typedef struct shaderpermutationinfo_s
1060 const char *pretext;
1063 shaderpermutationinfo_t;
1065 typedef struct shadermodeinfo_s
1067 const char *vertexfilename;
1068 const char *geometryfilename;
1069 const char *fragmentfilename;
1070 const char *pretext;
1075 typedef enum shaderpermutation_e
1077 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1078 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1079 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1080 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1081 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1082 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1083 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1084 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1085 SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1086 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1087 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1088 SHADERPERMUTATION_GAMMA = 1<<11, // gamma (postprocessing only)
1089 SHADERPERMUTATION_LIMIT = 1<<12, // size of permutations array
1090 SHADERPERMUTATION_COUNT = 12 // size of shaderpermutationinfo array
1092 shaderpermutation_t;
1094 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1095 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1097 {"#define USEDIFFUSE\n", " diffuse"},
1098 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1099 {"#define USECOLORMAPPING\n", " colormapping"},
1100 {"#define USECONTRASTBOOST\n", " contrastboost"},
1101 {"#define USEFOG\n", " fog"},
1102 {"#define USECUBEFILTER\n", " cubefilter"},
1103 {"#define USEGLOW\n", " glow"},
1104 {"#define USESPECULAR\n", " specular"},
1105 {"#define USEREFLECTION\n", " reflection"},
1106 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1107 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1108 {"#define USEGAMMA\n", " gamma"},
1111 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1112 typedef enum shadermode_e
1114 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1115 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1116 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1117 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1118 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1119 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1120 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1121 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1122 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1123 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1124 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1125 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1130 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1131 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1133 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1134 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1135 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1136 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1137 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1138 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1139 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1140 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1141 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1142 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1143 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1144 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1147 typedef struct r_glsl_permutation_s
1149 // indicates if we have tried compiling this permutation already
1151 // 0 if compilation failed
1153 // locations of detected uniforms in program object, or -1 if not found
1154 int loc_Texture_First;
1155 int loc_Texture_Second;
1156 int loc_Texture_Normal;
1157 int loc_Texture_Color;
1158 int loc_Texture_Gloss;
1159 int loc_Texture_Glow;
1160 int loc_Texture_SecondaryNormal;
1161 int loc_Texture_SecondaryColor;
1162 int loc_Texture_SecondaryGloss;
1163 int loc_Texture_SecondaryGlow;
1164 int loc_Texture_Pants;
1165 int loc_Texture_Shirt;
1166 int loc_Texture_FogMask;
1167 int loc_Texture_Lightmap;
1168 int loc_Texture_Deluxemap;
1169 int loc_Texture_Attenuation;
1170 int loc_Texture_Cube;
1171 int loc_Texture_Refraction;
1172 int loc_Texture_Reflection;
1174 int loc_LightPosition;
1175 int loc_EyePosition;
1176 int loc_Color_Pants;
1177 int loc_Color_Shirt;
1178 int loc_FogRangeRecip;
1179 int loc_AmbientScale;
1180 int loc_DiffuseScale;
1181 int loc_SpecularScale;
1182 int loc_SpecularPower;
1184 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1185 int loc_OffsetMapping_Scale;
1187 int loc_AmbientColor;
1188 int loc_DiffuseColor;
1189 int loc_SpecularColor;
1191 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1192 int loc_GammaCoeff; // 1 / gamma
1193 int loc_DistortScaleRefractReflect;
1194 int loc_ScreenScaleRefractReflect;
1195 int loc_ScreenCenterRefractReflect;
1196 int loc_RefractColor;
1197 int loc_ReflectColor;
1198 int loc_ReflectFactor;
1199 int loc_ReflectOffset;
1206 r_glsl_permutation_t;
1208 // information about each possible shader permutation
1209 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1210 // currently selected permutation
1211 r_glsl_permutation_t *r_glsl_permutation;
1213 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1216 if (!filename || !filename[0])
1218 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1221 if (printfromdisknotice)
1222 Con_DPrint("from disk... ");
1223 return shaderstring;
1225 else if (!strcmp(filename, "glsl/default.glsl"))
1227 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1228 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1230 return shaderstring;
1233 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1236 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1237 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1238 int vertstrings_count = 0;
1239 int geomstrings_count = 0;
1240 int fragstrings_count = 0;
1241 char *vertexstring, *geometrystring, *fragmentstring;
1242 const char *vertstrings_list[32+3];
1243 const char *geomstrings_list[32+3];
1244 const char *fragstrings_list[32+3];
1245 char permutationname[256];
1252 permutationname[0] = 0;
1253 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1254 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1255 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1257 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1259 // the first pretext is which type of shader to compile as
1260 // (later these will all be bound together as a program object)
1261 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1262 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1263 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1265 // the second pretext is the mode (for example a light source)
1266 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1267 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1268 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1269 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1271 // now add all the permutation pretexts
1272 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1274 if (permutation & (1<<i))
1276 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1277 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1278 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1279 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1283 // keep line numbers correct
1284 vertstrings_list[vertstrings_count++] = "\n";
1285 geomstrings_list[geomstrings_count++] = "\n";
1286 fragstrings_list[fragstrings_count++] = "\n";
1290 // now append the shader text itself
1291 vertstrings_list[vertstrings_count++] = vertexstring;
1292 geomstrings_list[geomstrings_count++] = geometrystring;
1293 fragstrings_list[fragstrings_count++] = fragmentstring;
1295 // if any sources were NULL, clear the respective list
1297 vertstrings_count = 0;
1298 if (!geometrystring)
1299 geomstrings_count = 0;
1300 if (!fragmentstring)
1301 fragstrings_count = 0;
1303 // compile the shader program
1304 if (vertstrings_count + geomstrings_count + fragstrings_count)
1305 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1309 qglUseProgramObjectARB(p->program);CHECKGLERROR
1310 // look up all the uniform variable names we care about, so we don't
1311 // have to look them up every time we set them
1312 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1313 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1314 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1315 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1316 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1317 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1318 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1319 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1320 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1321 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1322 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1323 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1324 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1325 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1326 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1327 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1328 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1329 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1330 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1331 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1332 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1333 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1334 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1335 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1336 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1337 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1338 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1339 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1340 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1341 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1342 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1343 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1344 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1345 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1346 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1347 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1348 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1349 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1350 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1351 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1352 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1353 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1354 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1355 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1356 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1357 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1358 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1359 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1360 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1361 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1362 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1363 // initialize the samplers to refer to the texture units we use
1364 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1365 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1366 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1367 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1368 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1369 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1370 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1371 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1372 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1373 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1374 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1375 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1376 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1377 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1378 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1379 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1380 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1381 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1382 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1384 if (developer.integer)
1385 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1388 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1392 Mem_Free(vertexstring);
1394 Mem_Free(geometrystring);
1396 Mem_Free(fragmentstring);
1399 void R_GLSL_Restart_f(void)
1402 shaderpermutation_t permutation;
1403 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1404 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1405 if (r_glsl_permutations[mode][permutation].program)
1406 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1407 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1410 void R_GLSL_DumpShader_f(void)
1414 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1417 Con_Printf("failed to write to glsl/default.glsl\n");
1421 FS_Print(file, "// The engine may define the following macros:\n");
1422 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1423 for (i = 0;i < SHADERMODE_COUNT;i++)
1424 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1425 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1426 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1427 FS_Print(file, "\n");
1428 FS_Print(file, builtinshaderstring);
1431 Con_Printf("glsl/default.glsl written\n");
1434 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1436 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1437 if (r_glsl_permutation != perm)
1439 r_glsl_permutation = perm;
1440 if (!r_glsl_permutation->program)
1442 if (!r_glsl_permutation->compiled)
1443 R_GLSL_CompilePermutation(mode, permutation);
1444 if (!r_glsl_permutation->program)
1446 // remove features until we find a valid permutation
1448 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1450 // reduce i more quickly whenever it would not remove any bits
1451 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1452 if (!(permutation & j))
1455 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1456 if (!r_glsl_permutation->compiled)
1457 R_GLSL_CompilePermutation(mode, permutation);
1458 if (r_glsl_permutation->program)
1461 if (i >= SHADERPERMUTATION_COUNT)
1463 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");
1464 Cvar_SetValueQuick(&r_glsl, 0);
1465 R_GLSL_Restart_f(); // unload shaders
1466 return; // no bit left to clear
1471 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1475 void R_SetupGenericShader(qboolean usetexture)
1477 if (gl_support_fragment_shader)
1479 if (r_glsl.integer && r_glsl_usegeneric.integer)
1480 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1481 else if (r_glsl_permutation)
1483 r_glsl_permutation = NULL;
1484 qglUseProgramObjectARB(0);CHECKGLERROR
1489 void R_SetupGenericTwoTextureShader(int texturemode)
1491 if (gl_support_fragment_shader)
1493 if (r_glsl.integer && r_glsl_usegeneric.integer)
1494 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1495 else if (r_glsl_permutation)
1497 r_glsl_permutation = NULL;
1498 qglUseProgramObjectARB(0);CHECKGLERROR
1501 if (!r_glsl_permutation)
1503 if (texturemode == GL_DECAL && gl_combine.integer)
1504 texturemode = GL_INTERPOLATE_ARB;
1505 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1509 void R_SetupDepthOrShadowShader(void)
1511 if (gl_support_fragment_shader)
1513 if (r_glsl.integer && r_glsl_usegeneric.integer)
1514 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1515 else if (r_glsl_permutation)
1517 r_glsl_permutation = NULL;
1518 qglUseProgramObjectARB(0);CHECKGLERROR
1523 extern rtexture_t *r_shadow_attenuationgradienttexture;
1524 extern rtexture_t *r_shadow_attenuation2dtexture;
1525 extern rtexture_t *r_shadow_attenuation3dtexture;
1526 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1528 // select a permutation of the lighting shader appropriate to this
1529 // combination of texture, entity, light source, and fogging, only use the
1530 // minimum features necessary to avoid wasting rendering time in the
1531 // fragment shader on features that are not being used
1532 unsigned int permutation = 0;
1533 shadermode_t mode = 0;
1534 // TODO: implement geometry-shader based shadow volumes someday
1535 if (r_glsl_offsetmapping.integer)
1537 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1538 if (r_glsl_offsetmapping_reliefmapping.integer)
1539 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1541 if (rsurfacepass == RSURFPASS_BACKGROUND)
1543 // distorted background
1544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1545 mode = SHADERMODE_WATER;
1547 mode = SHADERMODE_REFRACTION;
1549 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1552 mode = SHADERMODE_LIGHTSOURCE;
1553 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1554 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1555 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1556 permutation |= SHADERPERMUTATION_CUBEFILTER;
1557 if (diffusescale > 0)
1558 permutation |= SHADERPERMUTATION_DIFFUSE;
1559 if (specularscale > 0)
1560 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1561 if (r_refdef.fogenabled)
1562 permutation |= SHADERPERMUTATION_FOG;
1563 if (rsurface.texture->colormapping)
1564 permutation |= SHADERPERMUTATION_COLORMAPPING;
1565 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1566 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1568 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1570 // unshaded geometry (fullbright or ambient model lighting)
1571 mode = SHADERMODE_FLATCOLOR;
1572 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1573 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1574 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1575 permutation |= SHADERPERMUTATION_GLOW;
1576 if (r_refdef.fogenabled)
1577 permutation |= SHADERPERMUTATION_FOG;
1578 if (rsurface.texture->colormapping)
1579 permutation |= SHADERPERMUTATION_COLORMAPPING;
1580 if (r_glsl_offsetmapping.integer)
1582 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1583 if (r_glsl_offsetmapping_reliefmapping.integer)
1584 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1586 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1587 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1588 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1589 permutation |= SHADERPERMUTATION_REFLECTION;
1591 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1593 // directional model lighting
1594 mode = SHADERMODE_LIGHTDIRECTION;
1595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1596 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1597 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1598 permutation |= SHADERPERMUTATION_GLOW;
1599 permutation |= SHADERPERMUTATION_DIFFUSE;
1600 if (specularscale > 0)
1601 permutation |= SHADERPERMUTATION_SPECULAR;
1602 if (r_refdef.fogenabled)
1603 permutation |= SHADERPERMUTATION_FOG;
1604 if (rsurface.texture->colormapping)
1605 permutation |= SHADERPERMUTATION_COLORMAPPING;
1606 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1607 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1608 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1609 permutation |= SHADERPERMUTATION_REFLECTION;
1611 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1613 // ambient model lighting
1614 mode = SHADERMODE_LIGHTDIRECTION;
1615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1616 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1617 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1618 permutation |= SHADERPERMUTATION_GLOW;
1619 if (r_refdef.fogenabled)
1620 permutation |= SHADERPERMUTATION_FOG;
1621 if (rsurface.texture->colormapping)
1622 permutation |= SHADERPERMUTATION_COLORMAPPING;
1623 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1624 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1625 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1626 permutation |= SHADERPERMUTATION_REFLECTION;
1631 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1633 // deluxemapping (light direction texture)
1634 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1635 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1637 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1638 permutation |= SHADERPERMUTATION_DIFFUSE;
1639 if (specularscale > 0)
1640 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1642 else if (r_glsl_deluxemapping.integer >= 2)
1644 // fake deluxemapping (uniform light direction in tangentspace)
1645 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1646 permutation |= SHADERPERMUTATION_DIFFUSE;
1647 if (specularscale > 0)
1648 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1650 else if (rsurface.uselightmaptexture)
1652 // ordinary lightmapping (q1bsp, q3bsp)
1653 mode = SHADERMODE_LIGHTMAP;
1657 // ordinary vertex coloring (q3bsp)
1658 mode = SHADERMODE_VERTEXCOLOR;
1660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1661 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1662 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1663 permutation |= SHADERPERMUTATION_GLOW;
1664 if (r_refdef.fogenabled)
1665 permutation |= SHADERPERMUTATION_FOG;
1666 if (rsurface.texture->colormapping)
1667 permutation |= SHADERPERMUTATION_COLORMAPPING;
1668 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1669 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1670 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1671 permutation |= SHADERPERMUTATION_REFLECTION;
1673 R_SetupShader_SetPermutation(mode, permutation);
1674 if (mode == SHADERMODE_LIGHTSOURCE)
1676 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1677 if (permutation & SHADERPERMUTATION_DIFFUSE)
1679 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1680 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1681 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1682 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1686 // ambient only is simpler
1687 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1688 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1689 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1690 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1692 // additive passes are only darkened by fog, not tinted
1693 if (r_glsl_permutation->loc_FogColor >= 0)
1694 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1698 if (mode == SHADERMODE_LIGHTDIRECTION)
1700 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
1701 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
1702 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1703 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1707 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1708 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1709 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1711 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1712 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1713 // additive passes are only darkened by fog, not tinted
1714 if (r_glsl_permutation->loc_FogColor >= 0)
1716 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1717 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1719 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1721 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1722 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]);
1723 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]);
1724 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1725 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1726 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1727 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1729 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1731 // The formula used is actually:
1732 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1733 // color.rgb *= SceneBrightness;
1735 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1736 // and do [[calculations]] here in the engine
1737 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1738 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1741 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1742 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1743 if (r_glsl_permutation->loc_Color_Pants >= 0)
1745 if (rsurface.texture->currentskinframe->pants)
1746 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1748 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1750 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1752 if (rsurface.texture->currentskinframe->shirt)
1753 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1755 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1757 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1758 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1759 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1763 #define SKINFRAME_HASH 1024
1767 int loadsequence; // incremented each level change
1768 memexpandablearray_t array;
1769 skinframe_t *hash[SKINFRAME_HASH];
1773 void R_SkinFrame_PrepareForPurge(void)
1775 r_skinframe.loadsequence++;
1776 // wrap it without hitting zero
1777 if (r_skinframe.loadsequence >= 200)
1778 r_skinframe.loadsequence = 1;
1781 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1785 // mark the skinframe as used for the purging code
1786 skinframe->loadsequence = r_skinframe.loadsequence;
1789 void R_SkinFrame_Purge(void)
1793 for (i = 0;i < SKINFRAME_HASH;i++)
1795 for (s = r_skinframe.hash[i];s;s = s->next)
1797 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1799 if (s->merged == s->base)
1801 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1802 R_PurgeTexture(s->stain );s->stain = NULL;
1803 R_PurgeTexture(s->merged);s->merged = NULL;
1804 R_PurgeTexture(s->base );s->base = NULL;
1805 R_PurgeTexture(s->pants );s->pants = NULL;
1806 R_PurgeTexture(s->shirt );s->shirt = NULL;
1807 R_PurgeTexture(s->nmap );s->nmap = NULL;
1808 R_PurgeTexture(s->gloss );s->gloss = NULL;
1809 R_PurgeTexture(s->glow );s->glow = NULL;
1810 R_PurgeTexture(s->fog );s->fog = NULL;
1811 s->loadsequence = 0;
1817 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1819 char basename[MAX_QPATH];
1821 Image_StripImageExtension(name, basename, sizeof(basename));
1823 if( last == NULL ) {
1825 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1826 item = r_skinframe.hash[hashindex];
1831 // linearly search through the hash bucket
1832 for( ; item ; item = item->next ) {
1833 if( !strcmp( item->basename, basename ) ) {
1840 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1844 char basename[MAX_QPATH];
1846 Image_StripImageExtension(name, basename, sizeof(basename));
1848 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1849 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1850 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1854 rtexture_t *dyntexture;
1855 // check whether its a dynamic texture
1856 dyntexture = CL_GetDynTexture( basename );
1857 if (!add && !dyntexture)
1859 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1860 memset(item, 0, sizeof(*item));
1861 strlcpy(item->basename, basename, sizeof(item->basename));
1862 item->base = dyntexture; // either NULL or dyntexture handle
1863 item->textureflags = textureflags;
1864 item->comparewidth = comparewidth;
1865 item->compareheight = compareheight;
1866 item->comparecrc = comparecrc;
1867 item->next = r_skinframe.hash[hashindex];
1868 r_skinframe.hash[hashindex] = item;
1870 else if( item->base == NULL )
1872 rtexture_t *dyntexture;
1873 // check whether its a dynamic texture
1874 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1875 dyntexture = CL_GetDynTexture( basename );
1876 item->base = dyntexture; // either NULL or dyntexture handle
1879 R_SkinFrame_MarkUsed(item);
1883 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1885 // FIXME: it should be possible to disable loading various layers using
1886 // cvars, to prevent wasted loading time and memory usage if the user does
1888 qboolean loadnormalmap = true;
1889 qboolean loadgloss = true;
1890 qboolean loadpantsandshirt = true;
1891 qboolean loadglow = true;
1893 unsigned char *pixels;
1894 unsigned char *bumppixels;
1895 unsigned char *basepixels = NULL;
1896 int basepixels_width;
1897 int basepixels_height;
1898 skinframe_t *skinframe;
1900 if (cls.state == ca_dedicated)
1903 // return an existing skinframe if already loaded
1904 // if loading of the first image fails, don't make a new skinframe as it
1905 // would cause all future lookups of this to be missing
1906 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1907 if (skinframe && skinframe->base)
1910 basepixels = loadimagepixelsbgra(name, complain, true);
1911 if (basepixels == NULL)
1914 // we've got some pixels to store, so really allocate this new texture now
1916 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1917 skinframe->stain = NULL;
1918 skinframe->merged = NULL;
1919 skinframe->base = r_texture_notexture;
1920 skinframe->pants = NULL;
1921 skinframe->shirt = NULL;
1922 skinframe->nmap = r_texture_blanknormalmap;
1923 skinframe->gloss = NULL;
1924 skinframe->glow = NULL;
1925 skinframe->fog = NULL;
1927 basepixels_width = image_width;
1928 basepixels_height = image_height;
1929 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1931 if (textureflags & TEXF_ALPHA)
1933 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1934 if (basepixels[j] < 255)
1936 if (j < basepixels_width * basepixels_height * 4)
1938 // has transparent pixels
1939 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1940 for (j = 0;j < image_width * image_height * 4;j += 4)
1945 pixels[j+3] = basepixels[j+3];
1947 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1952 // _norm is the name used by tenebrae and has been adopted as standard
1955 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1957 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1961 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1963 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1964 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1965 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1967 Mem_Free(bumppixels);
1969 else if (r_shadow_bumpscale_basetexture.value > 0)
1971 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1972 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1973 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1977 // _luma is supported for tenebrae compatibility
1978 // (I think it's a very stupid name, but oh well)
1979 // _glow is the preferred name
1980 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1981 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1982 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1983 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1986 Mem_Free(basepixels);
1991 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)
1996 for (i = 0;i < width*height;i++)
1997 if (((unsigned char *)&palette[in[i]])[3] > 0)
1999 if (i == width*height)
2002 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2005 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2006 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2009 unsigned char *temp1, *temp2;
2010 skinframe_t *skinframe;
2012 if (cls.state == ca_dedicated)
2015 // if already loaded just return it, otherwise make a new skinframe
2016 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2017 if (skinframe && skinframe->base)
2020 skinframe->stain = NULL;
2021 skinframe->merged = NULL;
2022 skinframe->base = r_texture_notexture;
2023 skinframe->pants = NULL;
2024 skinframe->shirt = NULL;
2025 skinframe->nmap = r_texture_blanknormalmap;
2026 skinframe->gloss = NULL;
2027 skinframe->glow = NULL;
2028 skinframe->fog = NULL;
2030 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2034 if (r_shadow_bumpscale_basetexture.value > 0)
2036 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2037 temp2 = temp1 + width * height * 4;
2038 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2039 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2042 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2043 if (textureflags & TEXF_ALPHA)
2045 for (i = 3;i < width * height * 4;i += 4)
2046 if (skindata[i] < 255)
2048 if (i < width * height * 4)
2050 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2051 memcpy(fogpixels, skindata, width * height * 4);
2052 for (i = 0;i < width * height * 4;i += 4)
2053 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2054 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2055 Mem_Free(fogpixels);
2062 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2065 unsigned char *temp1, *temp2;
2066 skinframe_t *skinframe;
2068 if (cls.state == ca_dedicated)
2071 // if already loaded just return it, otherwise make a new skinframe
2072 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2073 if (skinframe && skinframe->base)
2076 skinframe->stain = NULL;
2077 skinframe->merged = NULL;
2078 skinframe->base = r_texture_notexture;
2079 skinframe->pants = NULL;
2080 skinframe->shirt = NULL;
2081 skinframe->nmap = r_texture_blanknormalmap;
2082 skinframe->gloss = NULL;
2083 skinframe->glow = NULL;
2084 skinframe->fog = NULL;
2086 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2090 if (r_shadow_bumpscale_basetexture.value > 0)
2092 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2093 temp2 = temp1 + width * height * 4;
2094 // use either a custom palette or the quake palette
2095 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2096 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2097 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2100 // use either a custom palette, or the quake palette
2101 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
2102 if (loadglowtexture)
2103 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2104 if (loadpantsandshirt)
2106 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2107 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2109 if (skinframe->pants || skinframe->shirt)
2110 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2111 if (textureflags & TEXF_ALPHA)
2113 for (i = 0;i < width * height;i++)
2114 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2116 if (i < width * height)
2117 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2123 skinframe_t *R_SkinFrame_LoadMissing(void)
2125 skinframe_t *skinframe;
2127 if (cls.state == ca_dedicated)
2130 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2131 skinframe->stain = NULL;
2132 skinframe->merged = NULL;
2133 skinframe->base = r_texture_notexture;
2134 skinframe->pants = NULL;
2135 skinframe->shirt = NULL;
2136 skinframe->nmap = r_texture_blanknormalmap;
2137 skinframe->gloss = NULL;
2138 skinframe->glow = NULL;
2139 skinframe->fog = NULL;
2144 void gl_main_start(void)
2146 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2147 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2149 // set up r_skinframe loading system for textures
2150 memset(&r_skinframe, 0, sizeof(r_skinframe));
2151 r_skinframe.loadsequence = 1;
2152 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2154 r_main_texturepool = R_AllocTexturePool();
2155 R_BuildBlankTextures();
2157 if (gl_texturecubemap)
2160 R_BuildNormalizationCube();
2162 r_texture_fogattenuation = NULL;
2163 //r_texture_fogintensity = NULL;
2164 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2165 memset(&r_waterstate, 0, sizeof(r_waterstate));
2166 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2167 memset(&r_svbsp, 0, sizeof (r_svbsp));
2169 r_refdef.fogmasktable_density = 0;
2172 void gl_main_shutdown(void)
2174 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2175 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2177 // clear out the r_skinframe state
2178 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2179 memset(&r_skinframe, 0, sizeof(r_skinframe));
2182 Mem_Free(r_svbsp.nodes);
2183 memset(&r_svbsp, 0, sizeof (r_svbsp));
2184 R_FreeTexturePool(&r_main_texturepool);
2185 r_texture_blanknormalmap = NULL;
2186 r_texture_white = NULL;
2187 r_texture_grey128 = NULL;
2188 r_texture_black = NULL;
2189 r_texture_whitecube = NULL;
2190 r_texture_normalizationcube = NULL;
2191 r_texture_fogattenuation = NULL;
2192 //r_texture_fogintensity = NULL;
2193 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2194 memset(&r_waterstate, 0, sizeof(r_waterstate));
2198 extern void CL_ParseEntityLump(char *entitystring);
2199 void gl_main_newmap(void)
2201 // FIXME: move this code to client
2203 char *entities, entname[MAX_QPATH];
2206 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2207 l = (int)strlen(entname) - 4;
2208 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2210 memcpy(entname + l, ".ent", 5);
2211 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2213 CL_ParseEntityLump(entities);
2218 if (cl.worldmodel->brush.entities)
2219 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2223 void GL_Main_Init(void)
2225 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2227 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2228 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2229 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2230 if (gamemode == GAME_NEHAHRA)
2232 Cvar_RegisterVariable (&gl_fogenable);
2233 Cvar_RegisterVariable (&gl_fogdensity);
2234 Cvar_RegisterVariable (&gl_fogred);
2235 Cvar_RegisterVariable (&gl_foggreen);
2236 Cvar_RegisterVariable (&gl_fogblue);
2237 Cvar_RegisterVariable (&gl_fogstart);
2238 Cvar_RegisterVariable (&gl_fogend);
2239 Cvar_RegisterVariable (&gl_skyclip);
2241 Cvar_RegisterVariable(&r_depthfirst);
2242 Cvar_RegisterVariable(&r_nearclip);
2243 Cvar_RegisterVariable(&r_showbboxes);
2244 Cvar_RegisterVariable(&r_showsurfaces);
2245 Cvar_RegisterVariable(&r_showtris);
2246 Cvar_RegisterVariable(&r_shownormals);
2247 Cvar_RegisterVariable(&r_showlighting);
2248 Cvar_RegisterVariable(&r_showshadowvolumes);
2249 Cvar_RegisterVariable(&r_showcollisionbrushes);
2250 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2251 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2252 Cvar_RegisterVariable(&r_showdisabledepthtest);
2253 Cvar_RegisterVariable(&r_drawportals);
2254 Cvar_RegisterVariable(&r_drawentities);
2255 Cvar_RegisterVariable(&r_cullentities_trace);
2256 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2257 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2258 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2259 Cvar_RegisterVariable(&r_drawviewmodel);
2260 Cvar_RegisterVariable(&r_speeds);
2261 Cvar_RegisterVariable(&r_fullbrights);
2262 Cvar_RegisterVariable(&r_wateralpha);
2263 Cvar_RegisterVariable(&r_dynamic);
2264 Cvar_RegisterVariable(&r_fullbright);
2265 Cvar_RegisterVariable(&r_shadows);
2266 Cvar_RegisterVariable(&r_shadows_throwdistance);
2267 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2268 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2269 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2270 Cvar_RegisterVariable(&r_fog_exp2);
2271 Cvar_RegisterVariable(&r_textureunits);
2272 Cvar_RegisterVariable(&r_glsl);
2273 Cvar_RegisterVariable(&r_glsl_contrastboost);
2274 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2275 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2276 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2277 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2278 Cvar_RegisterVariable(&r_glsl_postprocess);
2279 Cvar_RegisterVariable(&r_glsl_postprocess_contrastboost);
2280 Cvar_RegisterVariable(&r_glsl_postprocess_gamma);
2281 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2282 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2283 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2284 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2285 Cvar_RegisterVariable(&r_glsl_usegeneric);
2286 Cvar_RegisterVariable(&r_water);
2287 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2288 Cvar_RegisterVariable(&r_water_clippingplanebias);
2289 Cvar_RegisterVariable(&r_water_refractdistort);
2290 Cvar_RegisterVariable(&r_water_reflectdistort);
2291 Cvar_RegisterVariable(&r_lerpsprites);
2292 Cvar_RegisterVariable(&r_lerpmodels);
2293 Cvar_RegisterVariable(&r_lerplightstyles);
2294 Cvar_RegisterVariable(&r_waterscroll);
2295 Cvar_RegisterVariable(&r_bloom);
2296 Cvar_RegisterVariable(&r_bloom_colorscale);
2297 Cvar_RegisterVariable(&r_bloom_brighten);
2298 Cvar_RegisterVariable(&r_bloom_blur);
2299 Cvar_RegisterVariable(&r_bloom_resolution);
2300 Cvar_RegisterVariable(&r_bloom_colorexponent);
2301 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2302 Cvar_RegisterVariable(&r_hdr);
2303 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2304 Cvar_RegisterVariable(&r_hdr_glowintensity);
2305 Cvar_RegisterVariable(&r_hdr_range);
2306 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2307 Cvar_RegisterVariable(&developer_texturelogging);
2308 Cvar_RegisterVariable(&gl_lightmaps);
2309 Cvar_RegisterVariable(&r_test);
2310 Cvar_RegisterVariable(&r_batchmode);
2311 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2312 Cvar_SetValue("r_fullbrights", 0);
2313 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2315 Cvar_RegisterVariable(&r_track_sprites);
2316 Cvar_RegisterVariable(&r_track_sprites_flags);
2317 Cvar_RegisterVariable(&r_track_sprites_scalew);
2318 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2321 extern void R_Textures_Init(void);
2322 extern void GL_Draw_Init(void);
2323 extern void GL_Main_Init(void);
2324 extern void R_Shadow_Init(void);
2325 extern void R_Sky_Init(void);
2326 extern void GL_Surf_Init(void);
2327 extern void R_Particles_Init(void);
2328 extern void R_Explosion_Init(void);
2329 extern void gl_backend_init(void);
2330 extern void Sbar_Init(void);
2331 extern void R_LightningBeams_Init(void);
2332 extern void Mod_RenderInit(void);
2334 void Render_Init(void)
2346 R_LightningBeams_Init();
2355 extern char *ENGINE_EXTENSIONS;
2358 VID_CheckExtensions();
2360 // LordHavoc: report supported extensions
2361 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2363 // clear to black (loading plaque will be seen over this)
2365 qglClearColor(0,0,0,1);CHECKGLERROR
2366 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2369 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2373 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2375 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2378 p = r_refdef.view.frustum + i;
2383 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2387 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2391 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2395 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2399 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2403 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2407 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2411 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2419 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2423 for (i = 0;i < numplanes;i++)
2430 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2434 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2438 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2442 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2446 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2450 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2454 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2458 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2466 //==================================================================================
2468 static void R_View_UpdateEntityVisible (void)
2471 entity_render_t *ent;
2473 if (!r_drawentities.integer)
2476 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2477 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2479 // worldmodel can check visibility
2480 for (i = 0;i < r_refdef.scene.numentities;i++)
2482 ent = r_refdef.scene.entities[i];
2483 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
2486 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2488 for (i = 0;i < r_refdef.scene.numentities;i++)
2490 ent = r_refdef.scene.entities[i];
2491 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2493 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2494 ent->last_trace_visibility = realtime;
2495 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2496 r_refdef.viewcache.entityvisible[i] = 0;
2503 // no worldmodel or it can't check visibility
2504 for (i = 0;i < r_refdef.scene.numentities;i++)
2506 ent = r_refdef.scene.entities[i];
2507 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2512 // only used if skyrendermasked, and normally returns false
2513 int R_DrawBrushModelsSky (void)
2516 entity_render_t *ent;
2518 if (!r_drawentities.integer)
2522 for (i = 0;i < r_refdef.scene.numentities;i++)
2524 if (!r_refdef.viewcache.entityvisible[i])
2526 ent = r_refdef.scene.entities[i];
2527 if (!ent->model || !ent->model->DrawSky)
2529 ent->model->DrawSky(ent);
2535 static void R_DrawNoModel(entity_render_t *ent);
2536 static void R_DrawModels(void)
2539 entity_render_t *ent;
2541 if (!r_drawentities.integer)
2544 for (i = 0;i < r_refdef.scene.numentities;i++)
2546 if (!r_refdef.viewcache.entityvisible[i])
2548 ent = r_refdef.scene.entities[i];
2549 r_refdef.stats.entities++;
2550 if (ent->model && ent->model->Draw != NULL)
2551 ent->model->Draw(ent);
2557 static void R_DrawModelsDepth(void)
2560 entity_render_t *ent;
2562 if (!r_drawentities.integer)
2565 for (i = 0;i < r_refdef.scene.numentities;i++)
2567 if (!r_refdef.viewcache.entityvisible[i])
2569 ent = r_refdef.scene.entities[i];
2570 if (ent->model && ent->model->DrawDepth != NULL)
2571 ent->model->DrawDepth(ent);
2575 static void R_DrawModelsDebug(void)
2578 entity_render_t *ent;
2580 if (!r_drawentities.integer)
2583 for (i = 0;i < r_refdef.scene.numentities;i++)
2585 if (!r_refdef.viewcache.entityvisible[i])
2587 ent = r_refdef.scene.entities[i];
2588 if (ent->model && ent->model->DrawDebug != NULL)
2589 ent->model->DrawDebug(ent);
2593 static void R_DrawModelsAddWaterPlanes(void)
2596 entity_render_t *ent;
2598 if (!r_drawentities.integer)
2601 for (i = 0;i < r_refdef.scene.numentities;i++)
2603 if (!r_refdef.viewcache.entityvisible[i])
2605 ent = r_refdef.scene.entities[i];
2606 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2607 ent->model->DrawAddWaterPlanes(ent);
2611 static void R_View_SetFrustum(void)
2614 double slopex, slopey;
2615 vec3_t forward, left, up, origin;
2617 // we can't trust r_refdef.view.forward and friends in reflected scenes
2618 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2621 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2622 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2623 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2624 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2625 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2626 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2627 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2628 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2629 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2630 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2631 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2632 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2636 zNear = r_refdef.nearclip;
2637 nudge = 1.0 - 1.0 / (1<<23);
2638 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2639 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2640 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2641 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2642 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2643 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2644 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2645 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2651 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2652 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2653 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2654 r_refdef.view.frustum[0].dist = m[15] - m[12];
2656 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2657 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2658 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2659 r_refdef.view.frustum[1].dist = m[15] + m[12];
2661 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2662 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2663 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2664 r_refdef.view.frustum[2].dist = m[15] - m[13];
2666 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2667 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2668 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2669 r_refdef.view.frustum[3].dist = m[15] + m[13];
2671 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2672 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2673 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2674 r_refdef.view.frustum[4].dist = m[15] - m[14];
2676 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2677 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2678 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2679 r_refdef.view.frustum[5].dist = m[15] + m[14];
2682 if (r_refdef.view.useperspective)
2684 slopex = 1.0 / r_refdef.view.frustum_x;
2685 slopey = 1.0 / r_refdef.view.frustum_y;
2686 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2687 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2688 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2689 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2690 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2692 // Leaving those out was a mistake, those were in the old code, and they
2693 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2694 // I couldn't reproduce it after adding those normalizations. --blub
2695 VectorNormalize(r_refdef.view.frustum[0].normal);
2696 VectorNormalize(r_refdef.view.frustum[1].normal);
2697 VectorNormalize(r_refdef.view.frustum[2].normal);
2698 VectorNormalize(r_refdef.view.frustum[3].normal);
2700 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2701 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2702 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2703 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2704 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2706 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2707 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2708 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2709 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2710 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2714 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2715 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2716 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2717 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2718 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2719 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2720 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2721 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2722 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2723 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2725 r_refdef.view.numfrustumplanes = 5;
2727 if (r_refdef.view.useclipplane)
2729 r_refdef.view.numfrustumplanes = 6;
2730 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2733 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2734 PlaneClassify(r_refdef.view.frustum + i);
2736 // LordHavoc: note to all quake engine coders, Quake had a special case
2737 // for 90 degrees which assumed a square view (wrong), so I removed it,
2738 // Quake2 has it disabled as well.
2740 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2741 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2742 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2743 //PlaneClassify(&frustum[0]);
2745 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2746 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2747 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2748 //PlaneClassify(&frustum[1]);
2750 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2751 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2752 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2753 //PlaneClassify(&frustum[2]);
2755 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2756 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2757 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2758 //PlaneClassify(&frustum[3]);
2761 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2762 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2763 //PlaneClassify(&frustum[4]);
2766 void R_View_Update(void)
2768 R_View_SetFrustum();
2769 R_View_WorldVisibility(r_refdef.view.useclipplane);
2770 R_View_UpdateEntityVisible();
2773 void R_SetupView(qboolean allowwaterclippingplane)
2775 if (!r_refdef.view.useperspective)
2776 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2777 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2778 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2780 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2782 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2784 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2786 // LordHavoc: couldn't figure out how to make this approach the
2787 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2788 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2789 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2790 dist = r_refdef.view.clipplane.dist;
2791 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2795 void R_ResetViewRendering2D(void)
2799 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2800 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2801 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2802 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2803 GL_Color(1, 1, 1, 1);
2804 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2805 GL_BlendFunc(GL_ONE, GL_ZERO);
2806 GL_AlphaTest(false);
2807 GL_ScissorTest(false);
2808 GL_DepthMask(false);
2809 GL_DepthRange(0, 1);
2810 GL_DepthTest(false);
2811 R_Mesh_Matrix(&identitymatrix);
2812 R_Mesh_ResetTextureState();
2813 GL_PolygonOffset(0, 0);
2814 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2815 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2816 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2817 qglStencilMask(~0);CHECKGLERROR
2818 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2819 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2820 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2821 R_SetupGenericShader(true);
2824 void R_ResetViewRendering3D(void)
2828 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2829 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2831 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2832 GL_Color(1, 1, 1, 1);
2833 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2834 GL_BlendFunc(GL_ONE, GL_ZERO);
2835 GL_AlphaTest(false);
2836 GL_ScissorTest(true);
2838 GL_DepthRange(0, 1);
2840 R_Mesh_Matrix(&identitymatrix);
2841 R_Mesh_ResetTextureState();
2842 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2843 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2844 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2845 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2846 qglStencilMask(~0);CHECKGLERROR
2847 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2848 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2849 GL_CullFace(r_refdef.view.cullface_back);
2850 R_SetupGenericShader(true);
2853 void R_RenderScene(qboolean addwaterplanes);
2855 static void R_Water_StartFrame(void)
2858 int waterwidth, waterheight, texturewidth, textureheight;
2859 r_waterstate_waterplane_t *p;
2861 // set waterwidth and waterheight to the water resolution that will be
2862 // used (often less than the screen resolution for faster rendering)
2863 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2864 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2866 // calculate desired texture sizes
2867 // can't use water if the card does not support the texture size
2868 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2869 texturewidth = textureheight = waterwidth = waterheight = 0;
2870 else if (gl_support_arb_texture_non_power_of_two)
2872 texturewidth = waterwidth;
2873 textureheight = waterheight;
2877 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2878 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2881 // allocate textures as needed
2882 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2884 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2885 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2887 if (p->texture_refraction)
2888 R_FreeTexture(p->texture_refraction);
2889 p->texture_refraction = NULL;
2890 if (p->texture_reflection)
2891 R_FreeTexture(p->texture_reflection);
2892 p->texture_reflection = NULL;
2894 memset(&r_waterstate, 0, sizeof(r_waterstate));
2895 r_waterstate.waterwidth = waterwidth;
2896 r_waterstate.waterheight = waterheight;
2897 r_waterstate.texturewidth = texturewidth;
2898 r_waterstate.textureheight = textureheight;
2901 if (r_waterstate.waterwidth)
2903 r_waterstate.enabled = true;
2905 // set up variables that will be used in shader setup
2906 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2907 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2908 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2909 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2912 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2913 r_waterstate.numwaterplanes = 0;
2916 static void R_Water_AddWaterPlane(msurface_t *surface)
2918 int triangleindex, planeindex;
2923 r_waterstate_waterplane_t *p;
2924 // just use the first triangle with a valid normal for any decisions
2925 VectorClear(normal);
2926 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2928 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2929 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2930 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2931 TriangleNormal(vert[0], vert[1], vert[2], normal);
2932 if (VectorLength2(normal) >= 0.001)
2936 // find a matching plane if there is one
2937 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2938 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2940 if (planeindex >= r_waterstate.maxwaterplanes)
2941 return; // nothing we can do, out of planes
2943 // if this triangle does not fit any known plane rendered this frame, add one
2944 if (planeindex >= r_waterstate.numwaterplanes)
2946 // store the new plane
2947 r_waterstate.numwaterplanes++;
2948 VectorCopy(normal, p->plane.normal);
2949 VectorNormalize(p->plane.normal);
2950 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2951 PlaneClassify(&p->plane);
2952 // flip the plane if it does not face the viewer
2953 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2955 VectorNegate(p->plane.normal, p->plane.normal);
2956 p->plane.dist *= -1;
2957 PlaneClassify(&p->plane);
2959 // clear materialflags and pvs
2960 p->materialflags = 0;
2961 p->pvsvalid = false;
2963 // merge this surface's materialflags into the waterplane
2964 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2965 // merge this surface's PVS into the waterplane
2966 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2967 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2968 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2970 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2975 static void R_Water_ProcessPlanes(void)
2977 r_refdef_view_t originalview;
2979 r_waterstate_waterplane_t *p;
2981 originalview = r_refdef.view;
2983 // make sure enough textures are allocated
2984 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2986 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2988 if (!p->texture_refraction)
2989 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2990 if (!p->texture_refraction)
2994 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2996 if (!p->texture_reflection)
2997 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2998 if (!p->texture_reflection)
3004 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3006 r_refdef.view.showdebug = false;
3007 r_refdef.view.width = r_waterstate.waterwidth;
3008 r_refdef.view.height = r_waterstate.waterheight;
3009 r_refdef.view.useclipplane = true;
3010 r_waterstate.renderingscene = true;
3012 // render the normal view scene and copy into texture
3013 // (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)
3014 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3016 r_refdef.view.clipplane = p->plane;
3017 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3018 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3019 PlaneClassify(&r_refdef.view.clipplane);
3021 R_RenderScene(false);
3023 // copy view into the screen texture
3024 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3025 GL_ActiveTexture(0);
3027 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3030 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3032 // render reflected scene and copy into texture
3033 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3034 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3035 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3036 r_refdef.view.clipplane = p->plane;
3037 // reverse the cullface settings for this render
3038 r_refdef.view.cullface_front = GL_FRONT;
3039 r_refdef.view.cullface_back = GL_BACK;
3040 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3042 r_refdef.view.usecustompvs = true;
3044 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3046 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3049 R_ResetViewRendering3D();
3050 R_ClearScreen(r_refdef.fogenabled);
3051 if (r_timereport_active)
3052 R_TimeReport("viewclear");
3054 R_RenderScene(false);
3056 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3057 GL_ActiveTexture(0);
3059 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3061 R_ResetViewRendering3D();
3062 R_ClearScreen(r_refdef.fogenabled);
3063 if (r_timereport_active)
3064 R_TimeReport("viewclear");
3067 r_refdef.view = originalview;
3068 r_refdef.view.clear = true;
3069 r_waterstate.renderingscene = false;
3073 r_refdef.view = originalview;
3074 r_waterstate.renderingscene = false;
3075 Cvar_SetValueQuick(&r_water, 0);
3076 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3080 void R_Bloom_StartFrame(void)
3082 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3084 // set bloomwidth and bloomheight to the bloom resolution that will be
3085 // used (often less than the screen resolution for faster rendering)
3086 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3087 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3088 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3089 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3090 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3092 // calculate desired texture sizes
3093 if (gl_support_arb_texture_non_power_of_two)
3095 screentexturewidth = r_refdef.view.width;
3096 screentextureheight = r_refdef.view.height;
3097 bloomtexturewidth = r_bloomstate.bloomwidth;
3098 bloomtextureheight = r_bloomstate.bloomheight;
3102 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3103 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3104 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3105 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3108 if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3110 Cvar_SetValueQuick(&r_hdr, 0);
3111 Cvar_SetValueQuick(&r_bloom, 0);
3114 if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3115 screentexturewidth = screentextureheight = 0;
3116 if (!r_hdr.integer && !r_bloom.integer)
3117 bloomtexturewidth = bloomtextureheight = 0;
3119 // allocate textures as needed
3120 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3122 if (r_bloomstate.texture_screen)
3123 R_FreeTexture(r_bloomstate.texture_screen);
3124 r_bloomstate.texture_screen = NULL;
3125 r_bloomstate.screentexturewidth = screentexturewidth;
3126 r_bloomstate.screentextureheight = screentextureheight;
3127 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3128 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3130 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3132 if (r_bloomstate.texture_bloom)
3133 R_FreeTexture(r_bloomstate.texture_bloom);
3134 r_bloomstate.texture_bloom = NULL;
3135 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3136 r_bloomstate.bloomtextureheight = bloomtextureheight;
3137 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3138 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3141 // set up a texcoord array for the full resolution screen image
3142 // (we have to keep this around to copy back during final render)
3143 r_bloomstate.screentexcoord2f[0] = 0;
3144 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3145 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3146 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3147 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3148 r_bloomstate.screentexcoord2f[5] = 0;
3149 r_bloomstate.screentexcoord2f[6] = 0;
3150 r_bloomstate.screentexcoord2f[7] = 0;
3152 // set up a texcoord array for the reduced resolution bloom image
3153 // (which will be additive blended over the screen image)
3154 r_bloomstate.bloomtexcoord2f[0] = 0;
3155 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3156 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3157 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3158 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3159 r_bloomstate.bloomtexcoord2f[5] = 0;
3160 r_bloomstate.bloomtexcoord2f[6] = 0;
3161 r_bloomstate.bloomtexcoord2f[7] = 0;
3163 if (r_hdr.integer || r_bloom.integer)
3165 r_bloomstate.enabled = true;
3166 r_bloomstate.hdr = r_hdr.integer != 0;
3170 void R_Bloom_CopyBloomTexture(float colorscale)
3172 r_refdef.stats.bloom++;
3174 // scale down screen texture to the bloom texture size
3176 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3177 GL_BlendFunc(GL_ONE, GL_ZERO);
3178 GL_Color(colorscale, colorscale, colorscale, 1);
3179 // TODO: optimize with multitexture or GLSL
3180 R_SetupGenericShader(true);
3181 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3182 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3183 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3184 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3186 // we now have a bloom image in the framebuffer
3187 // copy it into the bloom image texture for later processing
3188 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3189 GL_ActiveTexture(0);
3191 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3192 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3195 void R_Bloom_CopyHDRTexture(void)
3197 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3198 GL_ActiveTexture(0);
3200 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3201 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3204 void R_Bloom_MakeTexture(void)
3207 float xoffset, yoffset, r, brighten;
3209 r_refdef.stats.bloom++;
3211 R_ResetViewRendering2D();
3212 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3213 R_Mesh_ColorPointer(NULL, 0, 0);
3214 R_SetupGenericShader(true);
3216 // we have a bloom image in the framebuffer
3218 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3220 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3223 r = bound(0, r_bloom_colorexponent.value / x, 1);
3224 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3225 GL_Color(r, r, r, 1);
3226 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3227 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3228 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3229 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3231 // copy the vertically blurred bloom view to a texture
3232 GL_ActiveTexture(0);
3234 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3235 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3238 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3239 brighten = r_bloom_brighten.value;
3241 brighten *= r_hdr_range.value;
3242 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3243 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3245 for (dir = 0;dir < 2;dir++)
3247 // blend on at multiple vertical offsets to achieve a vertical blur
3248 // TODO: do offset blends using GLSL
3249 GL_BlendFunc(GL_ONE, GL_ZERO);
3250 for (x = -range;x <= range;x++)
3252 if (!dir){xoffset = 0;yoffset = x;}
3253 else {xoffset = x;yoffset = 0;}
3254 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3255 yoffset /= (float)r_bloomstate.bloomtextureheight;
3256 // compute a texcoord array with the specified x and y offset
3257 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3258 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3259 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3260 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3261 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3262 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3263 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3264 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3265 // this r value looks like a 'dot' particle, fading sharply to
3266 // black at the edges
3267 // (probably not realistic but looks good enough)
3268 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3269 //r = (dir ? 1.0f : brighten)/(range*2+1);
3270 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3271 GL_Color(r, r, r, 1);
3272 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3273 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3274 GL_BlendFunc(GL_ONE, GL_ONE);
3277 // copy the vertically blurred bloom view to a texture
3278 GL_ActiveTexture(0);
3280 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3281 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3284 // apply subtract last
3285 // (just like it would be in a GLSL shader)
3286 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3288 GL_BlendFunc(GL_ONE, GL_ZERO);
3289 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3290 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3291 GL_Color(1, 1, 1, 1);
3292 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3293 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3295 GL_BlendFunc(GL_ONE, GL_ONE);
3296 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3297 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3298 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3299 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3300 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3301 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3302 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3304 // copy the darkened bloom view to a texture
3305 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3306 GL_ActiveTexture(0);
3308 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3309 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3313 void R_HDR_RenderBloomTexture(void)
3315 int oldwidth, oldheight;
3316 float oldcolorscale;
3318 oldcolorscale = r_refdef.view.colorscale;
3319 oldwidth = r_refdef.view.width;
3320 oldheight = r_refdef.view.height;
3321 r_refdef.view.width = r_bloomstate.bloomwidth;
3322 r_refdef.view.height = r_bloomstate.bloomheight;
3324 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3325 // TODO: add exposure compensation features
3326 // TODO: add fp16 framebuffer support
3328 r_refdef.view.showdebug = false;
3329 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3331 R_ClearScreen(r_refdef.fogenabled);
3332 if (r_timereport_active)
3333 R_TimeReport("HDRclear");
3335 r_waterstate.numwaterplanes = 0;
3336 R_RenderScene(r_waterstate.enabled);
3337 r_refdef.view.showdebug = true;
3339 R_ResetViewRendering2D();
3341 R_Bloom_CopyHDRTexture();
3342 R_Bloom_MakeTexture();
3344 // restore the view settings
3345 r_refdef.view.width = oldwidth;
3346 r_refdef.view.height = oldheight;
3347 r_refdef.view.colorscale = oldcolorscale;
3349 R_ResetViewRendering3D();
3351 R_ClearScreen(r_refdef.fogenabled);
3352 if (r_timereport_active)
3353 R_TimeReport("viewclear");
3356 static void R_BlendView(void)
3358 if (r_bloomstate.texture_screen)
3360 // copy view into the screen texture
3361 R_ResetViewRendering2D();
3362 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3363 R_Mesh_ColorPointer(NULL, 0, 0);
3364 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3365 GL_ActiveTexture(0);CHECKGLERROR
3366 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3367 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3370 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3372 unsigned int permutation =
3373 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3374 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0);
3375 if(r_glsl_postprocess.value)
3377 (r_glsl_postprocess_contrastboost.value != 1 ? SHADERPERMUTATION_CONTRASTBOOST : 0)
3378 | (r_glsl_postprocess_gamma.value != 1 ? SHADERPERMUTATION_GAMMA : 0);
3380 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3382 // render simple bloom effect
3383 // copy the screen and shrink it and darken it for the bloom process
3384 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3385 // make the bloom texture
3386 R_Bloom_MakeTexture();
3389 R_ResetViewRendering2D();
3390 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3391 R_Mesh_ColorPointer(NULL, 0, 0);
3392 GL_Color(1, 1, 1, 1);
3393 GL_BlendFunc(GL_ONE, GL_ZERO);
3394 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3395 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3396 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3397 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3398 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3399 if (r_glsl_permutation->loc_TintColor >= 0)
3400 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3401 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
3402 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_postprocess_contrastboost.value - 1);
3403 if (r_glsl_permutation->loc_GammaCoeff >= 0)
3404 qglUniform1fARB(r_glsl_permutation->loc_GammaCoeff, 1 / r_glsl_postprocess_gamma.value);
3405 if (r_glsl_permutation->loc_ClientTime >= 0)
3406 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3407 if (r_glsl_permutation->loc_UserVec1 >= 0)
3409 float a=0, b=0, c=0, d=0;
3410 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3411 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3413 if (r_glsl_permutation->loc_UserVec2 >= 0)
3415 float a=0, b=0, c=0, d=0;
3416 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3417 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3419 if (r_glsl_permutation->loc_UserVec3 >= 0)
3421 float a=0, b=0, c=0, d=0;
3422 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3423 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3425 if (r_glsl_permutation->loc_UserVec4 >= 0)
3427 float a=0, b=0, c=0, d=0;
3428 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3429 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3431 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3432 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3438 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3440 // render high dynamic range bloom effect
3441 // the bloom texture was made earlier this render, so we just need to
3442 // blend it onto the screen...
3443 R_ResetViewRendering2D();
3444 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3445 R_Mesh_ColorPointer(NULL, 0, 0);
3446 R_SetupGenericShader(true);
3447 GL_Color(1, 1, 1, 1);
3448 GL_BlendFunc(GL_ONE, GL_ONE);
3449 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3450 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3451 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3452 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3454 else if (r_bloomstate.texture_bloom)
3456 // render simple bloom effect
3457 // copy the screen and shrink it and darken it for the bloom process
3458 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3459 // make the bloom texture
3460 R_Bloom_MakeTexture();
3461 // put the original screen image back in place and blend the bloom
3463 R_ResetViewRendering2D();
3464 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3465 R_Mesh_ColorPointer(NULL, 0, 0);
3466 GL_Color(1, 1, 1, 1);
3467 GL_BlendFunc(GL_ONE, GL_ZERO);
3468 // do both in one pass if possible
3469 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3470 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3471 if (r_textureunits.integer >= 2 && gl_combine.integer)
3473 R_SetupGenericTwoTextureShader(GL_ADD);
3474 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3475 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3479 R_SetupGenericShader(true);
3480 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3481 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3482 // now blend on the bloom texture
3483 GL_BlendFunc(GL_ONE, GL_ONE);
3484 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3485 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3487 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3488 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3490 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3492 // apply a color tint to the whole view
3493 R_ResetViewRendering2D();
3494 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3495 R_Mesh_ColorPointer(NULL, 0, 0);
3496 R_SetupGenericShader(false);
3497 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3498 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3499 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3503 void R_RenderScene(qboolean addwaterplanes);
3505 matrix4x4_t r_waterscrollmatrix;
3507 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3509 if (r_refdef.fog_density)
3511 r_refdef.fogcolor[0] = r_refdef.fog_red;
3512 r_refdef.fogcolor[1] = r_refdef.fog_green;
3513 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3517 VectorCopy(r_refdef.fogcolor, fogvec);
3518 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3520 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3521 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3522 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3523 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3525 // color.rgb *= ContrastBoost * SceneBrightness;
3526 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3527 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3528 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3529 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3534 void R_UpdateVariables(void)
3538 r_refdef.farclip = 4096;
3539 if (r_refdef.scene.worldmodel)
3540 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3541 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3543 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3544 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3545 r_refdef.polygonfactor = 0;
3546 r_refdef.polygonoffset = 0;
3547 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3548 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3550 r_refdef.rtworld = r_shadow_realtime_world.integer;
3551 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3552 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3553 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3554 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3555 if (r_showsurfaces.integer)
3557 r_refdef.rtworld = false;
3558 r_refdef.rtworldshadows = false;
3559 r_refdef.rtdlight = false;
3560 r_refdef.rtdlightshadows = false;
3561 r_refdef.lightmapintensity = 0;
3564 if (gamemode == GAME_NEHAHRA)
3566 if (gl_fogenable.integer)
3568 r_refdef.oldgl_fogenable = true;
3569 r_refdef.fog_density = gl_fogdensity.value;
3570 r_refdef.fog_red = gl_fogred.value;
3571 r_refdef.fog_green = gl_foggreen.value;
3572 r_refdef.fog_blue = gl_fogblue.value;
3573 r_refdef.fog_alpha = 1;
3574 r_refdef.fog_start = 0;
3575 r_refdef.fog_end = gl_skyclip.value;
3577 else if (r_refdef.oldgl_fogenable)
3579 r_refdef.oldgl_fogenable = false;
3580 r_refdef.fog_density = 0;
3581 r_refdef.fog_red = 0;
3582 r_refdef.fog_green = 0;
3583 r_refdef.fog_blue = 0;
3584 r_refdef.fog_alpha = 0;
3585 r_refdef.fog_start = 0;
3586 r_refdef.fog_end = 0;
3590 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3591 r_refdef.fog_start = max(0, r_refdef.fog_start);
3592 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3594 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3596 if (r_refdef.fog_density)
3598 r_refdef.fogenabled = true;
3599 // this is the point where the fog reaches 0.9986 alpha, which we
3600 // consider a good enough cutoff point for the texture
3601 // (0.9986 * 256 == 255.6)
3602 if (r_fog_exp2.integer)
3603 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3605 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3606 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3607 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3608 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3609 // fog color was already set
3610 // update the fog texture
3611 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3612 R_BuildFogTexture();
3615 r_refdef.fogenabled = false;
3618 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3619 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3625 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3626 if( scenetype != r_currentscenetype ) {
3627 // store the old scenetype
3628 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3629 r_currentscenetype = scenetype;
3630 // move in the new scene
3631 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3640 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3642 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3643 if( scenetype == r_currentscenetype ) {
3644 return &r_refdef.scene;
3646 return &r_scenes_store[ scenetype ];
3655 void R_RenderView(void)
3657 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3658 return; //Host_Error ("R_RenderView: NULL worldmodel");
3660 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3662 // break apart the view matrix into vectors for various purposes
3663 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3664 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3665 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3666 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3667 // make an inverted copy of the view matrix for tracking sprites
3668 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3670 R_Shadow_UpdateWorldLightSelection();
3672 R_Bloom_StartFrame();
3673 R_Water_StartFrame();
3676 if (r_timereport_active)
3677 R_TimeReport("viewsetup");
3679 R_ResetViewRendering3D();
3681 if (r_refdef.view.clear || r_refdef.fogenabled)
3683 R_ClearScreen(r_refdef.fogenabled);
3684 if (r_timereport_active)
3685 R_TimeReport("viewclear");
3687 r_refdef.view.clear = true;
3689 r_refdef.view.showdebug = true;
3691 // this produces a bloom texture to be used in R_BlendView() later
3693 R_HDR_RenderBloomTexture();
3695 r_waterstate.numwaterplanes = 0;
3696 R_RenderScene(r_waterstate.enabled);
3699 if (r_timereport_active)
3700 R_TimeReport("blendview");
3702 GL_Scissor(0, 0, vid.width, vid.height);
3703 GL_ScissorTest(false);
3707 extern void R_DrawLightningBeams (void);
3708 extern void VM_CL_AddPolygonsToMeshQueue (void);
3709 extern void R_DrawPortals (void);
3710 extern cvar_t cl_locs_show;
3711 static void R_DrawLocs(void);
3712 static void R_DrawEntityBBoxes(void);
3713 void R_RenderScene(qboolean addwaterplanes)
3715 r_refdef.stats.renders++;
3721 R_ResetViewRendering3D();
3724 if (r_timereport_active)
3725 R_TimeReport("watervis");
3727 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3729 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3730 if (r_timereport_active)
3731 R_TimeReport("waterworld");
3734 // don't let sound skip if going slow
3735 if (r_refdef.scene.extraupdate)
3738 R_DrawModelsAddWaterPlanes();
3739 if (r_timereport_active)
3740 R_TimeReport("watermodels");
3742 R_Water_ProcessPlanes();
3743 if (r_timereport_active)
3744 R_TimeReport("waterscenes");
3747 R_ResetViewRendering3D();
3749 // don't let sound skip if going slow
3750 if (r_refdef.scene.extraupdate)
3753 R_MeshQueue_BeginScene();
3758 if (r_timereport_active)
3759 R_TimeReport("visibility");
3761 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3763 if (cl.csqc_vidvars.drawworld)
3765 // don't let sound skip if going slow
3766 if (r_refdef.scene.extraupdate)
3769 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3771 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3772 if (r_timereport_active)
3773 R_TimeReport("worldsky");
3776 if (R_DrawBrushModelsSky() && r_timereport_active)
3777 R_TimeReport("bmodelsky");
3780 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3782 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3783 if (r_timereport_active)
3784 R_TimeReport("worlddepth");
3786 if (r_depthfirst.integer >= 2)
3788 R_DrawModelsDepth();
3789 if (r_timereport_active)
3790 R_TimeReport("modeldepth");
3793 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3795 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3796 if (r_timereport_active)
3797 R_TimeReport("world");
3800 // don't let sound skip if going slow
3801 if (r_refdef.scene.extraupdate)
3805 if (r_timereport_active)
3806 R_TimeReport("models");
3808 // don't let sound skip if going slow
3809 if (r_refdef.scene.extraupdate)
3812 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3814 R_DrawModelShadows();
3816 R_ResetViewRendering3D();
3818 // don't let sound skip if going slow
3819 if (r_refdef.scene.extraupdate)
3823 R_ShadowVolumeLighting(false);
3824 if (r_timereport_active)
3825 R_TimeReport("rtlights");
3827 // don't let sound skip if going slow
3828 if (r_refdef.scene.extraupdate)
3831 if (cl.csqc_vidvars.drawworld)
3833 R_DrawLightningBeams();
3834 if (r_timereport_active)
3835 R_TimeReport("lightning");
3838 if (r_timereport_active)
3839 R_TimeReport("decals");
3842 if (r_timereport_active)
3843 R_TimeReport("particles");
3846 if (r_timereport_active)
3847 R_TimeReport("explosions");
3850 R_SetupGenericShader(true);
3851 VM_CL_AddPolygonsToMeshQueue();
3853 if (r_refdef.view.showdebug)
3855 if (cl_locs_show.integer)
3858 if (r_timereport_active)
3859 R_TimeReport("showlocs");
3862 if (r_drawportals.integer)
3865 if (r_timereport_active)
3866 R_TimeReport("portals");
3869 if (r_showbboxes.value > 0)
3871 R_DrawEntityBBoxes();
3872 if (r_timereport_active)
3873 R_TimeReport("bboxes");
3877 R_SetupGenericShader(true);
3878 R_MeshQueue_RenderTransparent();
3879 if (r_timereport_active)
3880 R_TimeReport("drawtrans");
3882 R_SetupGenericShader(true);
3884 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3886 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3887 if (r_timereport_active)
3888 R_TimeReport("worlddebug");
3889 R_DrawModelsDebug();
3890 if (r_timereport_active)
3891 R_TimeReport("modeldebug");
3894 R_SetupGenericShader(true);
3896 if (cl.csqc_vidvars.drawworld)
3899 if (r_timereport_active)
3900 R_TimeReport("coronas");
3903 // don't let sound skip if going slow
3904 if (r_refdef.scene.extraupdate)
3907 R_ResetViewRendering2D();
3910 static const int bboxelements[36] =
3920 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3923 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3924 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3925 GL_DepthMask(false);
3926 GL_DepthRange(0, 1);
3927 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3928 R_Mesh_Matrix(&identitymatrix);
3929 R_Mesh_ResetTextureState();
3931 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3932 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3933 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3934 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3935 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3936 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3937 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3938 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3939 R_FillColors(color4f, 8, cr, cg, cb, ca);
3940 if (r_refdef.fogenabled)
3942 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3944 f1 = FogPoint_World(v);
3946 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3947 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3948 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3951 R_Mesh_VertexPointer(vertex3f, 0, 0);
3952 R_Mesh_ColorPointer(color4f, 0, 0);
3953 R_Mesh_ResetTextureState();
3954 R_SetupGenericShader(false);
3955 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3958 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3962 prvm_edict_t *edict;
3963 // this function draws bounding boxes of server entities
3966 R_SetupGenericShader(false);
3968 for (i = 0;i < numsurfaces;i++)
3970 edict = PRVM_EDICT_NUM(surfacelist[i]);
3971 switch ((int)edict->fields.server->solid)
3973 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3974 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3975 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3976 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3977 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3978 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3980 color[3] *= r_showbboxes.value;
3981 color[3] = bound(0, color[3], 1);
3982 GL_DepthTest(!r_showdisabledepthtest.integer);
3983 GL_CullFace(r_refdef.view.cullface_front);
3984 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3989 static void R_DrawEntityBBoxes(void)
3992 prvm_edict_t *edict;
3994 // this function draws bounding boxes of server entities
3998 for (i = 0;i < prog->num_edicts;i++)
4000 edict = PRVM_EDICT_NUM(i);
4001 if (edict->priv.server->free)
4003 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4004 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4009 int nomodelelements[24] =
4021 float nomodelvertex3f[6*3] =
4031 float nomodelcolor4f[6*4] =
4033 0.0f, 0.0f, 0.5f, 1.0f,
4034 0.0f, 0.0f, 0.5f, 1.0f,
4035 0.0f, 0.5f, 0.0f, 1.0f,
4036 0.0f, 0.5f, 0.0f, 1.0f,
4037 0.5f, 0.0f, 0.0f, 1.0f,
4038 0.5f, 0.0f, 0.0f, 1.0f
4041 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4046 // this is only called once per entity so numsurfaces is always 1, and
4047 // surfacelist is always {0}, so this code does not handle batches
4048 R_Mesh_Matrix(&ent->matrix);
4050 if (ent->flags & EF_ADDITIVE)
4052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4053 GL_DepthMask(false);
4055 else if (ent->alpha < 1)
4057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4058 GL_DepthMask(false);
4062 GL_BlendFunc(GL_ONE, GL_ZERO);
4065 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4066 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4067 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4068 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4069 R_SetupGenericShader(false);
4070 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4071 if (r_refdef.fogenabled)
4074 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4075 R_Mesh_ColorPointer(color4f, 0, 0);
4076 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4077 f1 = FogPoint_World(org);
4079 for (i = 0, c = color4f;i < 6;i++, c += 4)
4081 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4082 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4083 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4087 else if (ent->alpha != 1)
4089 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4090 R_Mesh_ColorPointer(color4f, 0, 0);
4091 for (i = 0, c = color4f;i < 6;i++, c += 4)
4095 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4096 R_Mesh_ResetTextureState();
4097 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4100 void R_DrawNoModel(entity_render_t *ent)
4103 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4104 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4105 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4107 // R_DrawNoModelCallback(ent, 0);
4110 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4112 vec3_t right1, right2, diff, normal;
4114 VectorSubtract (org2, org1, normal);
4116 // calculate 'right' vector for start
4117 VectorSubtract (r_refdef.view.origin, org1, diff);
4118 CrossProduct (normal, diff, right1);
4119 VectorNormalize (right1);
4121 // calculate 'right' vector for end
4122 VectorSubtract (r_refdef.view.origin, org2, diff);
4123 CrossProduct (normal, diff, right2);
4124 VectorNormalize (right2);
4126 vert[ 0] = org1[0] + width * right1[0];
4127 vert[ 1] = org1[1] + width * right1[1];
4128 vert[ 2] = org1[2] + width * right1[2];
4129 vert[ 3] = org1[0] - width * right1[0];
4130 vert[ 4] = org1[1] - width * right1[1];
4131 vert[ 5] = org1[2] - width * right1[2];
4132 vert[ 6] = org2[0] - width * right2[0];
4133 vert[ 7] = org2[1] - width * right2[1];
4134 vert[ 8] = org2[2] - width * right2[2];
4135 vert[ 9] = org2[0] + width * right2[0];
4136 vert[10] = org2[1] + width * right2[1];
4137 vert[11] = org2[2] + width * right2[2];
4140 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4142 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)
4147 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4148 fog = FogPoint_World(origin);
4150 R_Mesh_Matrix(&identitymatrix);
4151 GL_BlendFunc(blendfunc1, blendfunc2);
4157 GL_CullFace(r_refdef.view.cullface_front);
4160 GL_CullFace(r_refdef.view.cullface_back);
4161 GL_CullFace(GL_NONE);
4163 GL_DepthMask(false);
4164 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4165 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4166 GL_DepthTest(!depthdisable);
4168 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4169 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4170 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4171 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4172 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4173 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4174 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4175 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4176 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4177 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4178 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4179 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4181 R_Mesh_VertexPointer(vertex3f, 0, 0);
4182 R_Mesh_ColorPointer(NULL, 0, 0);
4183 R_Mesh_ResetTextureState();
4184 R_SetupGenericShader(true);
4185 R_Mesh_TexBind(0, R_GetTexture(texture));
4186 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4187 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4188 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4189 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4191 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4193 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4194 GL_BlendFunc(blendfunc1, GL_ONE);
4196 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4197 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4201 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4206 VectorSet(v, x, y, z);
4207 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4208 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4210 if (i == mesh->numvertices)
4212 if (mesh->numvertices < mesh->maxvertices)
4214 VectorCopy(v, vertex3f);
4215 mesh->numvertices++;
4217 return mesh->numvertices;
4223 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4227 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4228 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4229 e = mesh->element3i + mesh->numtriangles * 3;
4230 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4232 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4233 if (mesh->numtriangles < mesh->maxtriangles)
4238 mesh->numtriangles++;
4240 element[1] = element[2];
4244 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4248 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4249 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4250 e = mesh->element3i + mesh->numtriangles * 3;
4251 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4253 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4254 if (mesh->numtriangles < mesh->maxtriangles)
4259 mesh->numtriangles++;
4261 element[1] = element[2];
4265 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4266 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4268 int planenum, planenum2;
4271 mplane_t *plane, *plane2;
4273 double temppoints[2][256*3];
4274 // figure out how large a bounding box we need to properly compute this brush
4276 for (w = 0;w < numplanes;w++)
4277 maxdist = max(maxdist, planes[w].dist);
4278 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4279 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4280 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4284 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4285 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4287 if (planenum2 == planenum)
4289 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);
4292 if (tempnumpoints < 3)
4294 // generate elements forming a triangle fan for this polygon
4295 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4299 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)
4301 texturelayer_t *layer;
4302 layer = t->currentlayers + t->currentnumlayers++;
4304 layer->depthmask = depthmask;
4305 layer->blendfunc1 = blendfunc1;
4306 layer->blendfunc2 = blendfunc2;
4307 layer->texture = texture;
4308 layer->texmatrix = *matrix;
4309 layer->color[0] = r * r_refdef.view.colorscale;
4310 layer->color[1] = g * r_refdef.view.colorscale;
4311 layer->color[2] = b * r_refdef.view.colorscale;
4312 layer->color[3] = a;
4315 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4318 index = parms[2] + r_refdef.scene.time * parms[3];
4319 index -= floor(index);
4323 case Q3WAVEFUNC_NONE:
4324 case Q3WAVEFUNC_NOISE:
4325 case Q3WAVEFUNC_COUNT:
4328 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4329 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4330 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4331 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4332 case Q3WAVEFUNC_TRIANGLE:
4334 f = index - floor(index);
4345 return (float)(parms[0] + parms[1] * f);
4348 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4351 model_t *model = ent->model;
4354 q3shaderinfo_layer_tcmod_t *tcmod;
4356 // switch to an alternate material if this is a q1bsp animated material
4358 texture_t *texture = t;
4359 int s = ent->skinnum;
4360 if ((unsigned int)s >= (unsigned int)model->numskins)
4362 if (model->skinscenes)
4364 if (model->skinscenes[s].framecount > 1)
4365 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4367 s = model->skinscenes[s].firstframe;
4370 t = t + s * model->num_surfaces;
4373 // use an alternate animation if the entity's frame is not 0,
4374 // and only if the texture has an alternate animation
4375 if (ent->frame2 != 0 && t->anim_total[1])
4376 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4378 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4380 texture->currentframe = t;
4383 // update currentskinframe to be a qw skin or animation frame
4384 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4386 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4388 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4389 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4390 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);
4392 t->currentskinframe = r_qwskincache_skinframe[i];
4393 if (t->currentskinframe == NULL)
4394 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4396 else if (t->numskinframes >= 2)
4397 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4398 if (t->backgroundnumskinframes >= 2)
4399 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4401 t->currentmaterialflags = t->basematerialflags;
4402 t->currentalpha = ent->alpha;
4403 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4405 t->currentalpha *= r_wateralpha.value;
4407 * FIXME what is this supposed to do?
4408 // if rendering refraction/reflection, disable transparency
4409 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4410 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4413 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
4414 t->currentalpha *= t->r_water_wateralpha;
4415 if(!r_waterstate.enabled)
4416 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4417 if (!(ent->flags & RENDER_LIGHT))
4418 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4419 else if (rsurface.modeltexcoordlightmap2f == NULL)
4421 // pick a model lighting mode
4422 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4423 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4425 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4427 if (ent->effects & EF_ADDITIVE)
4428 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4429 else if (t->currentalpha < 1)
4430 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4431 if (ent->effects & EF_DOUBLESIDED)
4432 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4433 if (ent->effects & EF_NODEPTHTEST)
4434 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4435 if (ent->flags & RENDER_VIEWMODEL)
4436 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4437 if (t->backgroundnumskinframes)
4438 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4439 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4441 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4442 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4445 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4447 // there is no tcmod
4448 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4449 t->currenttexmatrix = r_waterscrollmatrix;
4451 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4454 switch(tcmod->tcmod)
4458 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4459 matrix = r_waterscrollmatrix;
4461 matrix = identitymatrix;
4463 case Q3TCMOD_ENTITYTRANSLATE:
4464 // this is used in Q3 to allow the gamecode to control texcoord
4465 // scrolling on the entity, which is not supported in darkplaces yet.
4466 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4468 case Q3TCMOD_ROTATE:
4469 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4470 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4471 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4474 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4476 case Q3TCMOD_SCROLL:
4477 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4479 case Q3TCMOD_STRETCH:
4480 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4481 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4483 case Q3TCMOD_TRANSFORM:
4484 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4485 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4486 VectorSet(tcmat + 6, 0 , 0 , 1);
4487 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4488 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4490 case Q3TCMOD_TURBULENT:
4491 // this is handled in the RSurf_PrepareVertices function
4492 matrix = identitymatrix;
4495 // either replace or concatenate the transformation
4497 t->currenttexmatrix = matrix;
4500 matrix4x4_t temp = t->currenttexmatrix;
4501 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4505 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4506 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4507 t->glosstexture = r_texture_black;
4508 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4509 t->backgroundglosstexture = r_texture_black;
4510 t->specularpower = r_shadow_glossexponent.value;
4511 // TODO: store reference values for these in the texture?
4512 t->specularscale = 0;
4513 if (r_shadow_gloss.integer > 0)
4515 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4517 if (r_shadow_glossintensity.value > 0)
4519 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4520 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4521 t->specularscale = r_shadow_glossintensity.value;
4524 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4526 t->glosstexture = r_texture_white;
4527 t->backgroundglosstexture = r_texture_white;
4528 t->specularscale = r_shadow_gloss2intensity.value;
4532 // lightmaps mode looks bad with dlights using actual texturing, so turn
4533 // off the colormap and glossmap, but leave the normalmap on as it still
4534 // accurately represents the shading involved
4535 if (gl_lightmaps.integer)
4537 t->basetexture = r_texture_grey128;
4538 t->backgroundbasetexture = NULL;
4539 t->specularscale = 0;
4540 t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4541 t->currentmaterialflags |= MATERIALFLAG_WALL;
4544 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4545 VectorClear(t->dlightcolor);
4546 t->currentnumlayers = 0;
4547 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4549 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4551 int blendfunc1, blendfunc2, depthmask;
4552 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4554 blendfunc1 = GL_SRC_ALPHA;
4555 blendfunc2 = GL_ONE;
4557 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4559 blendfunc1 = GL_SRC_ALPHA;
4560 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4562 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4564 blendfunc1 = t->customblendfunc[0];
4565 blendfunc2 = t->customblendfunc[1];
4569 blendfunc1 = GL_ONE;
4570 blendfunc2 = GL_ZERO;
4572 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4573 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4576 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4577 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4578 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4580 // fullbright is not affected by r_refdef.lightmapintensity
4581 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4582 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4583 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4584 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4585 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4589 vec3_t ambientcolor;
4591 // set the color tint used for lights affecting this surface
4592 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4594 // q3bsp has no lightmap updates, so the lightstylevalue that
4595 // would normally be baked into the lightmap must be
4596 // applied to the color
4597 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4598 if (ent->model->type == mod_brushq3)
4599 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4600 colorscale *= r_refdef.lightmapintensity;
4601 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4602 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4603 // basic lit geometry
4604 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4605 // add pants/shirt if needed
4606 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4607 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4608 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4609 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4610 // now add ambient passes if needed
4611 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4613 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4614 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4615 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4616 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4617 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4620 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4621 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->lightmapcolor[3]);
4622 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4624 // if this is opaque use alpha blend which will darken the earlier
4627 // if this is an alpha blended material, all the earlier passes
4628 // were darkened by fog already, so we only need to add the fog
4629 // color ontop through the fog mask texture
4631 // if this is an additive blended material, all the earlier passes
4632 // were darkened by fog already, and we should not add fog color
4633 // (because the background was not darkened, there is no fog color
4634 // that was lost behind it).
4635 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.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4642 void R_UpdateAllTextureInfo(entity_render_t *ent)
4646 for (i = 0;i < ent->model->num_texturesperskin;i++)
4647 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4650 rsurfacestate_t rsurface;
4652 void R_Mesh_ResizeArrays(int newvertices)
4655 if (rsurface.array_size >= newvertices)
4657 if (rsurface.array_modelvertex3f)
4658 Mem_Free(rsurface.array_modelvertex3f);
4659 rsurface.array_size = (newvertices + 1023) & ~1023;
4660 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4661 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4662 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4663 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4664 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4665 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4666 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4667 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4668 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4669 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4670 rsurface.array_color4f = base + rsurface.array_size * 27;
4671 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4674 void RSurf_ActiveWorldEntity(void)
4676 model_t *model = r_refdef.scene.worldmodel;
4677 if (rsurface.array_size < model->surfmesh.num_vertices)
4678 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4679 rsurface.matrix = identitymatrix;
4680 rsurface.inversematrix = identitymatrix;
4681 R_Mesh_Matrix(&identitymatrix);
4682 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4683 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4684 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4685 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4686 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4687 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4688 rsurface.frameblend[0].frame = 0;
4689 rsurface.frameblend[0].lerp = 1;
4690 rsurface.frameblend[1].frame = 0;
4691 rsurface.frameblend[1].lerp = 0;
4692 rsurface.frameblend[2].frame = 0;
4693 rsurface.frameblend[2].lerp = 0;
4694 rsurface.frameblend[3].frame = 0;
4695 rsurface.frameblend[3].lerp = 0;
4696 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4697 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4698 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4699 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4700 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4701 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4702 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4703 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4704 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4705 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4706 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4707 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4708 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4709 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4710 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4711 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4712 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4713 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4714 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4715 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4716 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4717 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4718 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4719 rsurface.modelelement3i = model->surfmesh.data_element3i;
4720 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4721 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4722 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4723 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4724 rsurface.modelsurfaces = model->data_surfaces;
4725 rsurface.generatedvertex = false;
4726 rsurface.vertex3f = rsurface.modelvertex3f;
4727 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4728 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4729 rsurface.svector3f = rsurface.modelsvector3f;
4730 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4731 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4732 rsurface.tvector3f = rsurface.modeltvector3f;
4733 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4734 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4735 rsurface.normal3f = rsurface.modelnormal3f;
4736 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4737 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4738 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4741 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4743 model_t *model = ent->model;
4744 if (rsurface.array_size < model->surfmesh.num_vertices)
4745 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4746 rsurface.matrix = ent->matrix;
4747 rsurface.inversematrix = ent->inversematrix;
4748 R_Mesh_Matrix(&rsurface.matrix);
4749 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4750 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4751 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4752 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4753 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4754 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4755 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4756 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4757 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4758 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4759 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4760 rsurface.frameblend[0] = ent->frameblend[0];
4761 rsurface.frameblend[1] = ent->frameblend[1];
4762 rsurface.frameblend[2] = ent->frameblend[2];
4763 rsurface.frameblend[3] = ent->frameblend[3];
4764 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4765 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4766 if (ent->model->brush.submodel)
4768 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4769 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4771 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4775 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4776 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4777 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4778 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4779 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4781 else if (wantnormals)
4783 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4784 rsurface.modelsvector3f = NULL;
4785 rsurface.modeltvector3f = NULL;
4786 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4787 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4791 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4792 rsurface.modelsvector3f = NULL;
4793 rsurface.modeltvector3f = NULL;
4794 rsurface.modelnormal3f = NULL;
4795 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4797 rsurface.modelvertex3f_bufferobject = 0;
4798 rsurface.modelvertex3f_bufferoffset = 0;
4799 rsurface.modelsvector3f_bufferobject = 0;
4800 rsurface.modelsvector3f_bufferoffset = 0;
4801 rsurface.modeltvector3f_bufferobject = 0;
4802 rsurface.modeltvector3f_bufferoffset = 0;
4803 rsurface.modelnormal3f_bufferobject = 0;
4804 rsurface.modelnormal3f_bufferoffset = 0;
4805 rsurface.generatedvertex = true;
4809 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4810 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4811 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4812 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4813 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4814 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4815 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4816 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4817 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4818 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4819 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4820 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4821 rsurface.generatedvertex = false;
4823 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4824 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4825 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4826 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4827 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4828 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4829 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4830 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4831 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4832 rsurface.modelelement3i = model->surfmesh.data_element3i;
4833 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4834 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4835 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4836 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4837 rsurface.modelsurfaces = model->data_surfaces;
4838 rsurface.vertex3f = rsurface.modelvertex3f;
4839 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4840 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4841 rsurface.svector3f = rsurface.modelsvector3f;
4842 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4843 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4844 rsurface.tvector3f = rsurface.modeltvector3f;
4845 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4846 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4847 rsurface.normal3f = rsurface.modelnormal3f;
4848 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4849 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4850 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4853 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4854 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4857 int texturesurfaceindex;
4862 const float *v1, *in_tc;
4864 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4866 q3shaderinfo_deform_t *deform;
4867 // 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
4868 if (rsurface.generatedvertex)
4870 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4871 generatenormals = true;
4872 for (i = 0;i < Q3MAXDEFORMS;i++)
4874 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4876 generatetangents = true;
4877 generatenormals = true;
4879 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4880 generatenormals = true;
4882 if (generatenormals && !rsurface.modelnormal3f)
4884 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4885 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4886 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4887 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4889 if (generatetangents && !rsurface.modelsvector3f)
4891 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4892 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4893 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4894 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4895 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4896 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4897 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);
4900 rsurface.vertex3f = rsurface.modelvertex3f;
4901 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4902 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4903 rsurface.svector3f = rsurface.modelsvector3f;
4904 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4905 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4906 rsurface.tvector3f = rsurface.modeltvector3f;
4907 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4908 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4909 rsurface.normal3f = rsurface.modelnormal3f;
4910 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4911 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4912 // if vertices are deformed (sprite flares and things in maps, possibly
4913 // water waves, bulges and other deformations), generate them into
4914 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4915 // (may be static model data or generated data for an animated model, or
4916 // the previous deform pass)
4917 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4919 switch (deform->deform)
4922 case Q3DEFORM_PROJECTIONSHADOW:
4923 case Q3DEFORM_TEXT0:
4924 case Q3DEFORM_TEXT1:
4925 case Q3DEFORM_TEXT2:
4926 case Q3DEFORM_TEXT3:
4927 case Q3DEFORM_TEXT4:
4928 case Q3DEFORM_TEXT5:
4929 case Q3DEFORM_TEXT6:
4930 case Q3DEFORM_TEXT7:
4933 case Q3DEFORM_AUTOSPRITE:
4934 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4935 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4936 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4937 VectorNormalize(newforward);
4938 VectorNormalize(newright);
4939 VectorNormalize(newup);
4940 // make deformed versions of only the model vertices used by the specified surfaces
4941 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4943 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4944 // a single autosprite surface can contain multiple sprites...
4945 for (j = 0;j < surface->num_vertices - 3;j += 4)
4947 VectorClear(center);
4948 for (i = 0;i < 4;i++)
4949 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4950 VectorScale(center, 0.25f, center);
4951 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4952 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4953 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4954 for (i = 0;i < 4;i++)
4956 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4957 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4960 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);
4961 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);
4963 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4964 rsurface.vertex3f_bufferobject = 0;
4965 rsurface.vertex3f_bufferoffset = 0;
4966 rsurface.svector3f = rsurface.array_deformedsvector3f;
4967 rsurface.svector3f_bufferobject = 0;
4968 rsurface.svector3f_bufferoffset = 0;
4969 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4970 rsurface.tvector3f_bufferobject = 0;
4971 rsurface.tvector3f_bufferoffset = 0;
4972 rsurface.normal3f = rsurface.array_deformednormal3f;
4973 rsurface.normal3f_bufferobject = 0;
4974 rsurface.normal3f_bufferoffset = 0;
4976 case Q3DEFORM_AUTOSPRITE2:
4977 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4978 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4979 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4980 VectorNormalize(newforward);
4981 VectorNormalize(newright);
4982 VectorNormalize(newup);
4983 // make deformed versions of only the model vertices used by the specified surfaces
4984 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4987 const float *v1, *v2;
4997 memset(shortest, 0, sizeof(shortest));
4998 // a single autosprite surface can contain multiple sprites...
4999 for (j = 0;j < surface->num_vertices - 3;j += 4)
5001 VectorClear(center);
5002 for (i = 0;i < 4;i++)
5003 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5004 VectorScale(center, 0.25f, center);
5005 // find the two shortest edges, then use them to define the
5006 // axis vectors for rotating around the central axis
5007 for (i = 0;i < 6;i++)
5009 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5010 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5012 Debug_PolygonBegin(NULL, 0);
5013 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5014 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);
5015 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5018 l = VectorDistance2(v1, v2);
5019 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5021 l += (1.0f / 1024.0f);
5022 if (shortest[0].length2 > l || i == 0)
5024 shortest[1] = shortest[0];
5025 shortest[0].length2 = l;
5026 shortest[0].v1 = v1;
5027 shortest[0].v2 = v2;
5029 else if (shortest[1].length2 > l || i == 1)
5031 shortest[1].length2 = l;
5032 shortest[1].v1 = v1;
5033 shortest[1].v2 = v2;
5036 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5037 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5039 Debug_PolygonBegin(NULL, 0);
5040 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5041 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);
5042 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5045 // this calculates the right vector from the shortest edge
5046 // and the up vector from the edge midpoints
5047 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5048 VectorNormalize(right);
5049 VectorSubtract(end, start, up);
5050 VectorNormalize(up);
5051 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5052 //VectorSubtract(rsurface.modelorg, center, forward);
5053 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5054 VectorNegate(forward, forward);
5055 VectorReflect(forward, 0, up, forward);
5056 VectorNormalize(forward);
5057 CrossProduct(up, forward, newright);
5058 VectorNormalize(newright);
5060 Debug_PolygonBegin(NULL, 0);
5061 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);
5062 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5063 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5067 Debug_PolygonBegin(NULL, 0);
5068 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5069 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5070 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5073 // rotate the quad around the up axis vector, this is made
5074 // especially easy by the fact we know the quad is flat,
5075 // so we only have to subtract the center position and
5076 // measure distance along the right vector, and then
5077 // multiply that by the newright vector and add back the
5079 // we also need to subtract the old position to undo the
5080 // displacement from the center, which we do with a
5081 // DotProduct, the subtraction/addition of center is also
5082 // optimized into DotProducts here
5083 l = DotProduct(right, center);
5084 for (i = 0;i < 4;i++)
5086 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5087 f = DotProduct(right, v1) - l;
5088 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5091 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);
5092 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);
5094 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5095 rsurface.vertex3f_bufferobject = 0;
5096 rsurface.vertex3f_bufferoffset = 0;
5097 rsurface.svector3f = rsurface.array_deformedsvector3f;
5098 rsurface.svector3f_bufferobject = 0;
5099 rsurface.svector3f_bufferoffset = 0;
5100 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5101 rsurface.tvector3f_bufferobject = 0;
5102 rsurface.tvector3f_bufferoffset = 0;
5103 rsurface.normal3f = rsurface.array_deformednormal3f;
5104 rsurface.normal3f_bufferobject = 0;
5105 rsurface.normal3f_bufferoffset = 0;
5107 case Q3DEFORM_NORMAL:
5108 // deform the normals to make reflections wavey
5109 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5111 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5112 for (j = 0;j < surface->num_vertices;j++)
5115 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5116 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5117 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5118 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5119 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5120 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5121 VectorNormalize(normal);
5123 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);
5125 rsurface.svector3f = rsurface.array_deformedsvector3f;
5126 rsurface.svector3f_bufferobject = 0;
5127 rsurface.svector3f_bufferoffset = 0;
5128 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5129 rsurface.tvector3f_bufferobject = 0;
5130 rsurface.tvector3f_bufferoffset = 0;
5131 rsurface.normal3f = rsurface.array_deformednormal3f;
5132 rsurface.normal3f_bufferobject = 0;
5133 rsurface.normal3f_bufferoffset = 0;
5136 // deform vertex array to make wavey water and flags and such
5137 waveparms[0] = deform->waveparms[0];
5138 waveparms[1] = deform->waveparms[1];
5139 waveparms[2] = deform->waveparms[2];
5140 waveparms[3] = deform->waveparms[3];
5141 // this is how a divisor of vertex influence on deformation
5142 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5143 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5144 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5146 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5147 for (j = 0;j < surface->num_vertices;j++)
5149 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5150 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5151 // if the wavefunc depends on time, evaluate it per-vertex
5154 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5155 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5157 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5160 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5161 rsurface.vertex3f_bufferobject = 0;
5162 rsurface.vertex3f_bufferoffset = 0;
5164 case Q3DEFORM_BULGE:
5165 // deform vertex array to make the surface have moving bulges
5166 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5168 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5169 for (j = 0;j < surface->num_vertices;j++)
5171 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5172 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5175 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5176 rsurface.vertex3f_bufferobject = 0;
5177 rsurface.vertex3f_bufferoffset = 0;
5180 // deform vertex array
5181 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5182 VectorScale(deform->parms, scale, waveparms);
5183 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5185 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5186 for (j = 0;j < surface->num_vertices;j++)
5187 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5189 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5190 rsurface.vertex3f_bufferobject = 0;
5191 rsurface.vertex3f_bufferoffset = 0;
5195 // generate texcoords based on the chosen texcoord source
5196 switch(rsurface.texture->tcgen.tcgen)
5199 case Q3TCGEN_TEXTURE:
5200 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5201 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5202 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5204 case Q3TCGEN_LIGHTMAP:
5205 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5206 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5207 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5209 case Q3TCGEN_VECTOR:
5210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5213 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)
5215 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5216 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5219 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5220 rsurface.texcoordtexture2f_bufferobject = 0;
5221 rsurface.texcoordtexture2f_bufferoffset = 0;
5223 case Q3TCGEN_ENVIRONMENT:
5224 // make environment reflections using a spheremap
5225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5227 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5228 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5229 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5230 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5231 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5233 float l, d, eyedir[3];
5234 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5235 l = 0.5f / VectorLength(eyedir);
5236 d = DotProduct(normal, eyedir)*2;
5237 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5238 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5241 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5242 rsurface.texcoordtexture2f_bufferobject = 0;
5243 rsurface.texcoordtexture2f_bufferoffset = 0;
5246 // the only tcmod that needs software vertex processing is turbulent, so
5247 // check for it here and apply the changes if needed
5248 // and we only support that as the first one
5249 // (handling a mixture of turbulent and other tcmods would be problematic
5250 // without punting it entirely to a software path)
5251 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5253 amplitude = rsurface.texture->tcmods[0].parms[1];
5254 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5255 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5257 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5258 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)
5260 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5261 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5264 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5265 rsurface.texcoordtexture2f_bufferobject = 0;
5266 rsurface.texcoordtexture2f_bufferoffset = 0;
5268 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5269 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5270 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5271 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5274 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5277 const msurface_t *surface = texturesurfacelist[0];
5278 const msurface_t *surface2;
5283 // TODO: lock all array ranges before render, rather than on each surface
5284 if (texturenumsurfaces == 1)
5286 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5287 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));
5289 else if (r_batchmode.integer == 2)
5291 #define MAXBATCHTRIANGLES 4096
5292 int batchtriangles = 0;
5293 int batchelements[MAXBATCHTRIANGLES*3];
5294 for (i = 0;i < texturenumsurfaces;i = j)
5296 surface = texturesurfacelist[i];
5298 if (surface->num_triangles > MAXBATCHTRIANGLES)
5300 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));
5303 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5304 batchtriangles = surface->num_triangles;
5305 firstvertex = surface->num_firstvertex;
5306 endvertex = surface->num_firstvertex + surface->num_vertices;
5307 for (;j < texturenumsurfaces;j++)
5309 surface2 = texturesurfacelist[j];
5310 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5312 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5313 batchtriangles += surface2->num_triangles;
5314 firstvertex = min(firstvertex, surface2->num_firstvertex);
5315 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5317 surface2 = texturesurfacelist[j-1];
5318 numvertices = endvertex - firstvertex;
5319 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5322 else if (r_batchmode.integer == 1)
5324 for (i = 0;i < texturenumsurfaces;i = j)
5326 surface = texturesurfacelist[i];
5327 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5328 if (texturesurfacelist[j] != surface2)
5330 surface2 = texturesurfacelist[j-1];
5331 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5332 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5333 GL_LockArrays(surface->num_firstvertex, numvertices);
5334 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5339 for (i = 0;i < texturenumsurfaces;i++)
5341 surface = texturesurfacelist[i];
5342 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5343 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));
5348 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5350 int i, planeindex, vertexindex;
5354 r_waterstate_waterplane_t *p, *bestp;
5355 msurface_t *surface;
5356 if (r_waterstate.renderingscene)
5358 for (i = 0;i < texturenumsurfaces;i++)
5360 surface = texturesurfacelist[i];
5361 if (lightmaptexunit >= 0)
5362 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5363 if (deluxemaptexunit >= 0)
5364 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5365 // pick the closest matching water plane
5368 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5371 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5373 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5374 d += fabs(PlaneDiff(vert, &p->plane));
5376 if (bestd > d || !bestp)
5384 if (refractiontexunit >= 0)
5385 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5386 if (reflectiontexunit >= 0)
5387 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5391 if (refractiontexunit >= 0)
5392 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5393 if (reflectiontexunit >= 0)
5394 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5396 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5397 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));
5401 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5405 const msurface_t *surface = texturesurfacelist[0];
5406 const msurface_t *surface2;
5411 // TODO: lock all array ranges before render, rather than on each surface
5412 if (texturenumsurfaces == 1)
5414 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5415 if (deluxemaptexunit >= 0)
5416 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5417 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5418 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));
5420 else if (r_batchmode.integer == 2)
5422 #define MAXBATCHTRIANGLES 4096
5423 int batchtriangles = 0;
5424 int batchelements[MAXBATCHTRIANGLES*3];
5425 for (i = 0;i < texturenumsurfaces;i = j)
5427 surface = texturesurfacelist[i];
5428 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5429 if (deluxemaptexunit >= 0)
5430 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5432 if (surface->num_triangles > MAXBATCHTRIANGLES)
5434 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));
5437 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5438 batchtriangles = surface->num_triangles;
5439 firstvertex = surface->num_firstvertex;
5440 endvertex = surface->num_firstvertex + surface->num_vertices;
5441 for (;j < texturenumsurfaces;j++)
5443 surface2 = texturesurfacelist[j];
5444 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5446 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5447 batchtriangles += surface2->num_triangles;
5448 firstvertex = min(firstvertex, surface2->num_firstvertex);
5449 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5451 surface2 = texturesurfacelist[j-1];
5452 numvertices = endvertex - firstvertex;
5453 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5456 else if (r_batchmode.integer == 1)
5459 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5460 for (i = 0;i < texturenumsurfaces;i = j)
5462 surface = texturesurfacelist[i];
5463 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5464 if (texturesurfacelist[j] != surface2)
5466 Con_Printf(" %i", j - i);
5469 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5471 for (i = 0;i < texturenumsurfaces;i = j)
5473 surface = texturesurfacelist[i];
5474 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5475 if (deluxemaptexunit >= 0)
5476 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5477 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5478 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5481 Con_Printf(" %i", j - i);
5483 surface2 = texturesurfacelist[j-1];
5484 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5485 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5486 GL_LockArrays(surface->num_firstvertex, numvertices);
5487 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5495 for (i = 0;i < texturenumsurfaces;i++)
5497 surface = texturesurfacelist[i];
5498 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5499 if (deluxemaptexunit >= 0)
5500 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5501 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5502 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));
5507 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5510 int texturesurfaceindex;
5511 if (r_showsurfaces.integer == 2)
5513 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5515 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5516 for (j = 0;j < surface->num_triangles;j++)
5518 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5519 GL_Color(f, f, f, 1);
5520 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)));
5526 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5528 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5529 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5530 GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5531 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5532 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));
5537 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5539 int texturesurfaceindex;
5543 if (rsurface.lightmapcolor4f)
5545 // generate color arrays for the surfaces in this list
5546 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5548 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5549 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)
5551 f = FogPoint_Model(v);
5561 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5563 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5564 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)
5566 f = FogPoint_Model(v);
5574 rsurface.lightmapcolor4f = rsurface.array_color4f;
5575 rsurface.lightmapcolor4f_bufferobject = 0;
5576 rsurface.lightmapcolor4f_bufferoffset = 0;
5579 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5581 int texturesurfaceindex;
5584 if (!rsurface.lightmapcolor4f)
5586 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5588 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5589 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)
5597 rsurface.lightmapcolor4f = rsurface.array_color4f;
5598 rsurface.lightmapcolor4f_bufferobject = 0;
5599 rsurface.lightmapcolor4f_bufferoffset = 0;
5602 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5605 rsurface.lightmapcolor4f = NULL;
5606 rsurface.lightmapcolor4f_bufferobject = 0;
5607 rsurface.lightmapcolor4f_bufferoffset = 0;
5608 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5609 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5610 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5611 GL_Color(r, g, b, a);
5612 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5615 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5617 // TODO: optimize applyfog && applycolor case
5618 // just apply fog if necessary, and tint the fog color array if necessary
5619 rsurface.lightmapcolor4f = NULL;
5620 rsurface.lightmapcolor4f_bufferobject = 0;
5621 rsurface.lightmapcolor4f_bufferoffset = 0;
5622 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5623 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5624 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5625 GL_Color(r, g, b, a);
5626 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5629 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5631 int texturesurfaceindex;
5635 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5637 // generate color arrays for the surfaces in this list
5638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5640 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5641 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5643 if (surface->lightmapinfo->samples)
5645 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5646 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5647 VectorScale(lm, scale, c);
5648 if (surface->lightmapinfo->styles[1] != 255)
5650 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5652 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5653 VectorMA(c, scale, lm, c);
5654 if (surface->lightmapinfo->styles[2] != 255)
5657 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5658 VectorMA(c, scale, lm, c);
5659 if (surface->lightmapinfo->styles[3] != 255)
5662 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5663 VectorMA(c, scale, lm, c);
5673 rsurface.lightmapcolor4f = rsurface.array_color4f;
5674 rsurface.lightmapcolor4f_bufferobject = 0;
5675 rsurface.lightmapcolor4f_bufferoffset = 0;
5679 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5680 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5681 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5683 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5684 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5685 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5686 GL_Color(r, g, b, a);
5687 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5690 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5692 int texturesurfaceindex;
5696 vec3_t ambientcolor;
5697 vec3_t diffusecolor;
5701 VectorCopy(rsurface.modellight_lightdir, lightdir);
5702 f = 0.5f * r_refdef.lightmapintensity;
5703 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5704 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5705 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5706 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5707 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5708 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5709 if (VectorLength2(diffusecolor) > 0)
5711 // generate color arrays for the surfaces in this list
5712 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5714 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5715 int numverts = surface->num_vertices;
5716 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5717 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5718 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5719 // q3-style directional shading
5720 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5722 if ((f = DotProduct(c2, lightdir)) > 0)
5723 VectorMA(ambientcolor, f, diffusecolor, c);
5725 VectorCopy(ambientcolor, c);
5734 rsurface.lightmapcolor4f = rsurface.array_color4f;
5735 rsurface.lightmapcolor4f_bufferobject = 0;
5736 rsurface.lightmapcolor4f_bufferoffset = 0;
5740 r = ambientcolor[0];
5741 g = ambientcolor[1];
5742 b = ambientcolor[2];
5743 rsurface.lightmapcolor4f = NULL;
5744 rsurface.lightmapcolor4f_bufferobject = 0;
5745 rsurface.lightmapcolor4f_bufferoffset = 0;
5747 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5748 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5749 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5750 GL_Color(r, g, b, a);
5751 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5754 void RSurf_SetupDepthAndCulling(void)
5756 // submodels are biased to avoid z-fighting with world surfaces that they
5757 // may be exactly overlapping (avoids z-fighting artifacts on certain
5758 // doors and things in Quake maps)
5759 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5760 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5761 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5762 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5765 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5767 // transparent sky would be ridiculous
5768 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5770 R_SetupGenericShader(false);
5773 skyrendernow = false;
5774 // we have to force off the water clipping plane while rendering sky
5778 // restore entity matrix
5779 R_Mesh_Matrix(&rsurface.matrix);
5781 RSurf_SetupDepthAndCulling();
5783 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5784 // skymasking on them, and Quake3 never did sky masking (unlike
5785 // software Quake and software Quake2), so disable the sky masking
5786 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5787 // and skymasking also looks very bad when noclipping outside the
5788 // level, so don't use it then either.
5789 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5791 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5792 R_Mesh_ColorPointer(NULL, 0, 0);
5793 R_Mesh_ResetTextureState();
5794 if (skyrendermasked)
5796 R_SetupDepthOrShadowShader();
5797 // depth-only (masking)
5798 GL_ColorMask(0,0,0,0);
5799 // just to make sure that braindead drivers don't draw
5800 // anything despite that colormask...
5801 GL_BlendFunc(GL_ZERO, GL_ONE);
5805 R_SetupGenericShader(false);
5807 GL_BlendFunc(GL_ONE, GL_ZERO);
5809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5811 if (skyrendermasked)
5812 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5814 R_Mesh_ResetTextureState();
5815 GL_Color(1, 1, 1, 1);
5818 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5820 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5823 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5824 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5825 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5826 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5827 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5828 if (rsurface.texture->backgroundcurrentskinframe)
5830 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5831 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5832 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5833 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5835 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5836 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5837 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5838 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5839 R_Mesh_ColorPointer(NULL, 0, 0);
5841 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5843 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5845 // render background
5846 GL_BlendFunc(GL_ONE, GL_ZERO);
5848 GL_AlphaTest(false);
5850 GL_Color(1, 1, 1, 1);
5851 R_Mesh_ColorPointer(NULL, 0, 0);
5853 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5854 if (r_glsl_permutation)
5856 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5857 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5858 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5859 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5860 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5861 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5862 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5864 GL_LockArrays(0, 0);
5866 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5867 GL_DepthMask(false);
5868 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5869 R_Mesh_ColorPointer(NULL, 0, 0);
5871 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5872 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5873 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5876 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5877 if (!r_glsl_permutation)
5880 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5881 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5882 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5883 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5884 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5885 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5887 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5889 GL_BlendFunc(GL_ONE, GL_ZERO);
5891 GL_AlphaTest(false);
5895 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5896 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5897 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5900 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5902 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5903 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5905 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5909 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5910 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5912 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5914 GL_LockArrays(0, 0);
5917 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5919 // OpenGL 1.3 path - anything not completely ancient
5920 int texturesurfaceindex;
5921 qboolean applycolor;
5925 const texturelayer_t *layer;
5926 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5928 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5931 int layertexrgbscale;
5932 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5934 if (layerindex == 0)
5938 GL_AlphaTest(false);
5939 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5942 GL_DepthMask(layer->depthmask && writedepth);
5943 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5944 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5946 layertexrgbscale = 4;
5947 VectorScale(layer->color, 0.25f, layercolor);
5949 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5951 layertexrgbscale = 2;
5952 VectorScale(layer->color, 0.5f, layercolor);
5956 layertexrgbscale = 1;
5957 VectorScale(layer->color, 1.0f, layercolor);
5959 layercolor[3] = layer->color[3];
5960 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5961 R_Mesh_ColorPointer(NULL, 0, 0);
5962 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5963 switch (layer->type)
5965 case TEXTURELAYERTYPE_LITTEXTURE:
5966 memset(&m, 0, sizeof(m));
5967 m.tex[0] = R_GetTexture(r_texture_white);
5968 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5969 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5970 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5971 m.tex[1] = R_GetTexture(layer->texture);
5972 m.texmatrix[1] = layer->texmatrix;
5973 m.texrgbscale[1] = layertexrgbscale;
5974 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5975 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5976 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5977 R_Mesh_TextureState(&m);
5978 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5979 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5980 else if (rsurface.uselightmaptexture)
5981 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5983 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5985 case TEXTURELAYERTYPE_TEXTURE:
5986 memset(&m, 0, sizeof(m));
5987 m.tex[0] = R_GetTexture(layer->texture);
5988 m.texmatrix[0] = layer->texmatrix;
5989 m.texrgbscale[0] = layertexrgbscale;
5990 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5991 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5992 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5993 R_Mesh_TextureState(&m);
5994 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5996 case TEXTURELAYERTYPE_FOG:
5997 memset(&m, 0, sizeof(m));
5998 m.texrgbscale[0] = layertexrgbscale;
6001 m.tex[0] = R_GetTexture(layer->texture);
6002 m.texmatrix[0] = layer->texmatrix;
6003 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6004 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6005 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6007 R_Mesh_TextureState(&m);
6008 // generate a color array for the fog pass
6009 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6010 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6014 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6015 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)
6017 f = 1 - FogPoint_Model(v);
6018 c[0] = layercolor[0];
6019 c[1] = layercolor[1];
6020 c[2] = layercolor[2];
6021 c[3] = f * layercolor[3];
6024 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6027 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6029 GL_LockArrays(0, 0);
6032 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6034 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6035 GL_AlphaTest(false);
6039 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6041 // OpenGL 1.1 - crusty old voodoo path
6042 int texturesurfaceindex;
6046 const texturelayer_t *layer;
6047 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6049 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6051 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6053 if (layerindex == 0)
6057 GL_AlphaTest(false);
6058 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6061 GL_DepthMask(layer->depthmask && writedepth);
6062 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6063 R_Mesh_ColorPointer(NULL, 0, 0);
6064 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6065 switch (layer->type)
6067 case TEXTURELAYERTYPE_LITTEXTURE:
6068 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6070 // two-pass lit texture with 2x rgbscale
6071 // first the lightmap pass
6072 memset(&m, 0, sizeof(m));
6073 m.tex[0] = R_GetTexture(r_texture_white);
6074 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6075 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6076 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6077 R_Mesh_TextureState(&m);
6078 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6079 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6080 else if (rsurface.uselightmaptexture)
6081 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6083 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6084 GL_LockArrays(0, 0);
6085 // then apply the texture to it
6086 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6087 memset(&m, 0, sizeof(m));
6088 m.tex[0] = R_GetTexture(layer->texture);
6089 m.texmatrix[0] = layer->texmatrix;
6090 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6091 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6092 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6093 R_Mesh_TextureState(&m);
6094 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);
6098 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6099 memset(&m, 0, sizeof(m));
6100 m.tex[0] = R_GetTexture(layer->texture);
6101 m.texmatrix[0] = layer->texmatrix;
6102 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6103 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6104 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6105 R_Mesh_TextureState(&m);
6106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6107 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);
6109 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);
6112 case TEXTURELAYERTYPE_TEXTURE:
6113 // singletexture unlit texture with transparency support
6114 memset(&m, 0, sizeof(m));
6115 m.tex[0] = R_GetTexture(layer->texture);
6116 m.texmatrix[0] = layer->texmatrix;
6117 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6118 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6119 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6120 R_Mesh_TextureState(&m);
6121 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);
6123 case TEXTURELAYERTYPE_FOG:
6124 // singletexture fogging
6125 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6128 memset(&m, 0, sizeof(m));
6129 m.tex[0] = R_GetTexture(layer->texture);
6130 m.texmatrix[0] = layer->texmatrix;
6131 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6132 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6133 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6134 R_Mesh_TextureState(&m);
6137 R_Mesh_ResetTextureState();
6138 // generate a color array for the fog pass
6139 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6143 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6144 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)
6146 f = 1 - FogPoint_Model(v);
6147 c[0] = layer->color[0];
6148 c[1] = layer->color[1];
6149 c[2] = layer->color[2];
6150 c[3] = f * layer->color[3];
6153 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6156 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6158 GL_LockArrays(0, 0);
6161 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6163 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6164 GL_AlphaTest(false);
6168 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6171 RSurf_SetupDepthAndCulling();
6172 if (r_glsl.integer && gl_support_fragment_shader)
6173 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6174 else if (gl_combine.integer && r_textureunits.integer >= 2)
6175 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6177 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6181 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6184 int texturenumsurfaces, endsurface;
6186 msurface_t *surface;
6187 msurface_t *texturesurfacelist[1024];
6189 // if the model is static it doesn't matter what value we give for
6190 // wantnormals and wanttangents, so this logic uses only rules applicable
6191 // to a model, knowing that they are meaningless otherwise
6192 if (ent == r_refdef.scene.worldentity)
6193 RSurf_ActiveWorldEntity();
6194 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6195 RSurf_ActiveModelEntity(ent, false, false);
6197 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6199 for (i = 0;i < numsurfaces;i = j)
6202 surface = rsurface.modelsurfaces + surfacelist[i];
6203 texture = surface->texture;
6204 R_UpdateTextureInfo(ent, texture);
6205 rsurface.texture = texture->currentframe;
6206 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6207 // scan ahead until we find a different texture
6208 endsurface = min(i + 1024, numsurfaces);
6209 texturenumsurfaces = 0;
6210 texturesurfacelist[texturenumsurfaces++] = surface;
6211 for (;j < endsurface;j++)
6213 surface = rsurface.modelsurfaces + surfacelist[j];
6214 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6216 texturesurfacelist[texturenumsurfaces++] = surface;
6218 // render the range of surfaces
6219 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6221 GL_AlphaTest(false);
6224 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6229 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6231 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6233 RSurf_SetupDepthAndCulling();
6234 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6235 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6237 else if (r_showsurfaces.integer)
6239 RSurf_SetupDepthAndCulling();
6241 GL_BlendFunc(GL_ONE, GL_ZERO);
6243 GL_AlphaTest(false);
6244 R_Mesh_ColorPointer(NULL, 0, 0);
6245 R_Mesh_ResetTextureState();
6246 R_SetupGenericShader(false);
6247 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6248 if (!r_refdef.view.showdebug)
6250 GL_Color(0, 0, 0, 1);
6251 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6254 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6256 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6257 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6258 else if (!rsurface.texture->currentnumlayers)
6260 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6262 // transparent surfaces get pushed off into the transparent queue
6263 int surfacelistindex;
6264 const msurface_t *surface;
6265 vec3_t tempcenter, center;
6266 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6268 surface = texturesurfacelist[surfacelistindex];
6269 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6270 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6271 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6272 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6273 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6278 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6279 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6284 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6288 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6291 for (i = 0;i < numsurfaces;i++)
6292 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6293 R_Water_AddWaterPlane(surfacelist[i]);
6296 // break the surface list down into batches by texture and use of lightmapping
6297 for (i = 0;i < numsurfaces;i = j)
6300 // texture is the base texture pointer, rsurface.texture is the
6301 // current frame/skin the texture is directing us to use (for example
6302 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6303 // use skin 1 instead)
6304 texture = surfacelist[i]->texture;
6305 rsurface.texture = texture->currentframe;
6306 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6307 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6309 // if this texture is not the kind we want, skip ahead to the next one
6310 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6314 // simply scan ahead until we find a different texture or lightmap state
6315 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6317 // render the range of surfaces
6318 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6322 float locboxvertex3f[6*4*3] =
6324 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6325 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6326 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6327 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6328 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6329 1,0,0, 0,0,0, 0,1,0, 1,1,0
6332 int locboxelement3i[6*2*3] =
6342 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6345 cl_locnode_t *loc = (cl_locnode_t *)ent;
6347 float vertex3f[6*4*3];
6349 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6350 GL_DepthMask(false);
6351 GL_DepthRange(0, 1);
6352 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6354 GL_CullFace(GL_NONE);
6355 R_Mesh_Matrix(&identitymatrix);
6357 R_Mesh_VertexPointer(vertex3f, 0, 0);
6358 R_Mesh_ColorPointer(NULL, 0, 0);
6359 R_Mesh_ResetTextureState();
6360 R_SetupGenericShader(false);
6363 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6364 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6365 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6366 surfacelist[0] < 0 ? 0.5f : 0.125f);
6368 if (VectorCompare(loc->mins, loc->maxs))
6370 VectorSet(size, 2, 2, 2);
6371 VectorMA(loc->mins, -0.5f, size, mins);
6375 VectorCopy(loc->mins, mins);
6376 VectorSubtract(loc->maxs, loc->mins, size);
6379 for (i = 0;i < 6*4*3;)
6380 for (j = 0;j < 3;j++, i++)
6381 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6383 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6386 void R_DrawLocs(void)
6389 cl_locnode_t *loc, *nearestloc;
6391 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6392 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6394 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6395 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6399 void R_DrawDebugModel(entity_render_t *ent)
6401 int i, j, k, l, flagsmask;
6402 const int *elements;
6404 msurface_t *surface;
6405 model_t *model = ent->model;
6408 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6410 R_Mesh_ColorPointer(NULL, 0, 0);
6411 R_Mesh_ResetTextureState();
6412 R_SetupGenericShader(false);
6413 GL_DepthRange(0, 1);
6414 GL_DepthTest(!r_showdisabledepthtest.integer);
6415 GL_DepthMask(false);
6416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6418 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6420 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6421 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6423 if (brush->colbrushf && brush->colbrushf->numtriangles)
6425 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6426 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6427 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6430 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6432 if (surface->num_collisiontriangles)
6434 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6435 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6436 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6441 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6443 if (r_showtris.integer || r_shownormals.integer)
6445 if (r_showdisabledepthtest.integer)
6447 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6448 GL_DepthMask(false);
6452 GL_BlendFunc(GL_ONE, GL_ZERO);
6455 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6457 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6459 rsurface.texture = surface->texture->currentframe;
6460 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6462 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6463 if (r_showtris.value > 0)
6465 if (!rsurface.texture->currentlayers->depthmask)
6466 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6467 else if (ent == r_refdef.scene.worldentity)
6468 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6470 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6471 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6474 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6476 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6477 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6478 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6479 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6484 if (r_shownormals.value > 0)
6487 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6489 VectorCopy(rsurface.vertex3f + l * 3, v);
6490 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6491 qglVertex3f(v[0], v[1], v[2]);
6492 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6493 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6494 qglVertex3f(v[0], v[1], v[2]);
6499 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6501 VectorCopy(rsurface.vertex3f + l * 3, v);
6502 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6503 qglVertex3f(v[0], v[1], v[2]);
6504 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6505 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6506 qglVertex3f(v[0], v[1], v[2]);
6511 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6513 VectorCopy(rsurface.vertex3f + l * 3, v);
6514 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6515 qglVertex3f(v[0], v[1], v[2]);
6516 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6517 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6518 qglVertex3f(v[0], v[1], v[2]);
6525 rsurface.texture = NULL;
6529 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6530 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6532 int i, j, endj, f, flagsmask;
6533 msurface_t *surface;
6535 model_t *model = r_refdef.scene.worldmodel;
6536 const int maxsurfacelist = 1024;
6537 int numsurfacelist = 0;
6538 msurface_t *surfacelist[1024];
6542 RSurf_ActiveWorldEntity();
6544 // update light styles on this submodel
6545 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6547 model_brush_lightstyleinfo_t *style;
6548 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6550 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6552 msurface_t *surfaces = model->data_surfaces;
6553 int *list = style->surfacelist;
6554 style->value = r_refdef.scene.lightstylevalue[style->style];
6555 for (j = 0;j < style->numsurfaces;j++)
6556 surfaces[list[j]].cached_dlight = true;
6561 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6562 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6566 R_DrawDebugModel(r_refdef.scene.worldentity);
6572 rsurface.uselightmaptexture = false;
6573 rsurface.texture = NULL;
6574 rsurface.rtlight = NULL;
6576 j = model->firstmodelsurface;
6577 endj = j + model->nummodelsurfaces;
6580 // quickly skip over non-visible surfaces
6581 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6583 // quickly iterate over visible surfaces
6584 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6586 // process this surface
6587 surface = model->data_surfaces + j;
6588 // if this surface fits the criteria, add it to the list
6589 if (surface->num_triangles)
6591 // if lightmap parameters changed, rebuild lightmap texture
6592 if (surface->cached_dlight)
6593 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6594 // add face to draw list
6595 surfacelist[numsurfacelist++] = surface;
6596 r_refdef.stats.world_triangles += surface->num_triangles;
6597 if (numsurfacelist >= maxsurfacelist)
6599 r_refdef.stats.world_surfaces += numsurfacelist;
6600 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6606 r_refdef.stats.world_surfaces += numsurfacelist;
6608 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6609 GL_AlphaTest(false);
6612 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6614 int i, j, f, flagsmask;
6615 msurface_t *surface, *endsurface;
6617 model_t *model = ent->model;
6618 const int maxsurfacelist = 1024;
6619 int numsurfacelist = 0;
6620 msurface_t *surfacelist[1024];
6624 // if the model is static it doesn't matter what value we give for
6625 // wantnormals and wanttangents, so this logic uses only rules applicable
6626 // to a model, knowing that they are meaningless otherwise
6627 if (ent == r_refdef.scene.worldentity)
6628 RSurf_ActiveWorldEntity();
6629 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6630 RSurf_ActiveModelEntity(ent, false, false);
6632 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6634 // update light styles
6635 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6637 model_brush_lightstyleinfo_t *style;
6638 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6640 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6642 msurface_t *surfaces = model->data_surfaces;
6643 int *list = style->surfacelist;
6644 style->value = r_refdef.scene.lightstylevalue[style->style];
6645 for (j = 0;j < style->numsurfaces;j++)
6646 surfaces[list[j]].cached_dlight = true;
6651 R_UpdateAllTextureInfo(ent);
6652 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6656 R_DrawDebugModel(ent);
6662 rsurface.uselightmaptexture = false;
6663 rsurface.texture = NULL;
6664 rsurface.rtlight = NULL;
6666 surface = model->data_surfaces + model->firstmodelsurface;
6667 endsurface = surface + model->nummodelsurfaces;
6668 for (;surface < endsurface;surface++)
6670 // if this surface fits the criteria, add it to the list
6671 if (surface->num_triangles)
6673 // if lightmap parameters changed, rebuild lightmap texture
6674 if (surface->cached_dlight)
6675 R_BuildLightMap(ent, surface);
6676 // add face to draw list
6677 surfacelist[numsurfacelist++] = surface;
6678 r_refdef.stats.entities_triangles += surface->num_triangles;
6679 if (numsurfacelist >= maxsurfacelist)
6681 r_refdef.stats.entities_surfaces += numsurfacelist;
6682 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6687 r_refdef.stats.entities_surfaces += numsurfacelist;
6689 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6690 GL_AlphaTest(false);