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;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
46 cvar_t r_motionblur_debug = {0, "r_motionblur_debug", "0", "outputs current motionblur alpha value"};
48 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "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"};
49 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
50 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
51 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
52 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)"};
53 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
54 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
55 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"};
56 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"};
57 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
58 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"};
59 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"};
60 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"};
61 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
62 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
63 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
64 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
65 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
66 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
67 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
68 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
69 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
70 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
71 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
72 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
73 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
74 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
75 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
76 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"};
77 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"};
78 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
79 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
81 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
82 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
83 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
84 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
85 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
86 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
87 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
88 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
90 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)"};
92 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
93 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
94 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)"};
95 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
96 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
97 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
98 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
99 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)"};
100 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)"};
101 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)"};
102 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)"};
103 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)"};
105 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)"};
106 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
107 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"};
108 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
109 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
111 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
112 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
113 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
114 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
116 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
117 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
118 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
119 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
120 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
121 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
122 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
124 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
125 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
126 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
127 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)"};
129 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"};
131 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"};
133 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
135 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
136 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
137 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"};
138 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
139 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
140 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
141 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
143 extern cvar_t v_glslgamma;
145 extern qboolean v_flipped_state;
147 static struct r_bloomstate_s
152 int bloomwidth, bloomheight;
154 int screentexturewidth, screentextureheight;
155 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
157 int bloomtexturewidth, bloomtextureheight;
158 rtexture_t *texture_bloom;
160 // arrays for rendering the screen passes
161 float screentexcoord2f[8];
162 float bloomtexcoord2f[8];
163 float offsettexcoord2f[8];
167 r_waterstate_t r_waterstate;
169 /// shadow volume bsp struct with automatically growing nodes buffer
172 rtexture_t *r_texture_blanknormalmap;
173 rtexture_t *r_texture_white;
174 rtexture_t *r_texture_grey128;
175 rtexture_t *r_texture_black;
176 rtexture_t *r_texture_notexture;
177 rtexture_t *r_texture_whitecube;
178 rtexture_t *r_texture_normalizationcube;
179 rtexture_t *r_texture_fogattenuation;
180 rtexture_t *r_texture_gammaramps;
181 unsigned int r_texture_gammaramps_serial;
182 //rtexture_t *r_texture_fogintensity;
184 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
185 unsigned int r_numqueries;
186 unsigned int r_maxqueries;
188 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
189 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
191 /// vertex coordinates for a quad that covers the screen exactly
192 const static float r_screenvertex3f[12] =
200 extern void R_DrawModelShadows(void);
202 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
205 for (i = 0;i < verts;i++)
216 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
219 for (i = 0;i < verts;i++)
229 // FIXME: move this to client?
232 if (gamemode == GAME_NEHAHRA)
234 Cvar_Set("gl_fogenable", "0");
235 Cvar_Set("gl_fogdensity", "0.2");
236 Cvar_Set("gl_fogred", "0.3");
237 Cvar_Set("gl_foggreen", "0.3");
238 Cvar_Set("gl_fogblue", "0.3");
240 r_refdef.fog_density = 0;
241 r_refdef.fog_red = 0;
242 r_refdef.fog_green = 0;
243 r_refdef.fog_blue = 0;
244 r_refdef.fog_alpha = 1;
245 r_refdef.fog_start = 0;
246 r_refdef.fog_end = 0;
249 float FogForDistance(vec_t dist)
251 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
252 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
255 float FogPoint_World(const vec3_t p)
257 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
260 float FogPoint_Model(const vec3_t p)
262 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
265 static void R_BuildBlankTextures(void)
267 unsigned char data[4];
268 data[2] = 128; // normal X
269 data[1] = 128; // normal Y
270 data[0] = 255; // normal Z
271 data[3] = 128; // height
272 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
277 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
282 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 static void R_BuildNoTexture(void)
293 unsigned char pix[16][16][4];
294 // this makes a light grey/dark grey checkerboard texture
295 for (y = 0;y < 16;y++)
297 for (x = 0;x < 16;x++)
299 if ((y < 8) ^ (x < 8))
315 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
318 static void R_BuildWhiteCube(void)
320 unsigned char data[6*1*1*4];
321 memset(data, 255, sizeof(data));
322 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
325 static void R_BuildNormalizationCube(void)
329 vec_t s, t, intensity;
331 unsigned char data[6][NORMSIZE][NORMSIZE][4];
332 for (side = 0;side < 6;side++)
334 for (y = 0;y < NORMSIZE;y++)
336 for (x = 0;x < NORMSIZE;x++)
338 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
339 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
374 intensity = 127.0f / sqrt(DotProduct(v, v));
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
376 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
377 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
378 data[side][y][x][3] = 255;
382 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
385 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 //unsigned char data2[FOGWIDTH][4];
393 r_refdef.fogmasktable_start = r_refdef.fog_start;
394 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
395 r_refdef.fogmasktable_range = r_refdef.fogrange;
396 r_refdef.fogmasktable_density = r_refdef.fog_density;
398 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
399 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
401 d = (x * r - r_refdef.fogmasktable_start);
402 if(developer.integer >= 100)
403 Con_Printf("%f ", d);
405 if (r_fog_exp2.integer)
406 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
408 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
409 if(developer.integer >= 100)
410 Con_Printf(" : %f ", alpha);
411 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
412 if(developer.integer >= 100)
413 Con_Printf(" = %f\n", alpha);
414 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
417 for (x = 0;x < FOGWIDTH;x++)
419 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
424 //data2[x][0] = 255 - b;
425 //data2[x][1] = 255 - b;
426 //data2[x][2] = 255 - b;
429 if (r_texture_fogattenuation)
431 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
432 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
436 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);
437 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
441 static const char *builtinshaderstring =
442 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
443 "// written by Forest 'LordHavoc' Hale\n"
445 "// common definitions between vertex shader and fragment shader:\n"
447 "//#ifdef __GLSL_CG_DATA_TYPES\n"
448 "//# define myhalf half\n"
449 "//# define myhalf2 half2\n"
450 "//# define myhalf3 half3\n"
451 "//# define myhalf4 half4\n"
453 "# define myhalf float\n"
454 "# define myhalf2 vec2\n"
455 "# define myhalf3 vec3\n"
456 "# define myhalf4 vec4\n"
459 "#ifdef MODE_DEPTH_OR_SHADOW\n"
461 "# ifdef VERTEX_SHADER\n"
464 " gl_Position = ftransform();\n"
470 "#ifdef MODE_POSTPROCESS\n"
471 "# ifdef VERTEX_SHADER\n"
474 " gl_FrontColor = gl_Color;\n"
475 " gl_Position = ftransform();\n"
476 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
478 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
482 "# ifdef FRAGMENT_SHADER\n"
484 "uniform sampler2D Texture_First;\n"
486 "uniform sampler2D Texture_Second;\n"
488 "#ifdef USEGAMMARAMPS\n"
489 "uniform sampler2D Texture_GammaRamps;\n"
491 "#ifdef USESATURATION\n"
492 "uniform float Saturation;\n"
494 "#ifdef USEVERTEXTEXTUREBLEND\n"
495 "uniform vec4 TintColor;\n"
497 "#ifdef USECOLORMOD\n"
498 "uniform vec3 Gamma;\n"
500 "//uncomment these if you want to use them:\n"
501 "uniform vec4 UserVec1;\n"
502 "// uniform vec4 UserVec2;\n"
503 "// uniform vec4 UserVec3;\n"
504 "// uniform vec4 UserVec4;\n"
505 "// uniform float ClientTime;\n"
506 "uniform vec2 PixelSize;\n"
509 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
511 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
513 "#ifdef USEVERTEXTEXTUREBLEND\n"
514 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
517 "#ifdef USEPOSTPROCESSING\n"
518 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
519 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
520 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
521 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
522 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
523 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
524 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
525 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
528 "#ifdef USESATURATION\n"
529 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
530 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
531 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
532 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
535 "#ifdef USEGAMMARAMPS\n"
536 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
537 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
538 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
545 "#ifdef MODE_GENERIC\n"
546 "# ifdef VERTEX_SHADER\n"
549 " gl_FrontColor = gl_Color;\n"
550 "# ifdef USEDIFFUSE\n"
551 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
553 "# ifdef USESPECULAR\n"
554 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
556 " gl_Position = ftransform();\n"
559 "# ifdef FRAGMENT_SHADER\n"
561 "# ifdef USEDIFFUSE\n"
562 "uniform sampler2D Texture_First;\n"
564 "# ifdef USESPECULAR\n"
565 "uniform sampler2D Texture_Second;\n"
570 " gl_FragColor = gl_Color;\n"
571 "# ifdef USEDIFFUSE\n"
572 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
575 "# ifdef USESPECULAR\n"
576 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
578 "# ifdef USECOLORMAPPING\n"
579 " gl_FragColor *= tex2;\n"
582 " gl_FragColor += tex2;\n"
584 "# ifdef USEVERTEXTEXTUREBLEND\n"
585 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
590 "#else // !MODE_GENERIC\n"
592 "varying vec2 TexCoord;\n"
593 "#ifdef USEVERTEXTEXTUREBLEND\n"
594 "varying vec2 TexCoord2;\n"
596 "varying vec2 TexCoordLightmap;\n"
598 "#ifdef MODE_LIGHTSOURCE\n"
599 "varying vec3 CubeVector;\n"
602 "#ifdef MODE_LIGHTSOURCE\n"
603 "varying vec3 LightVector;\n"
605 "#ifdef MODE_LIGHTDIRECTION\n"
606 "varying vec3 LightVector;\n"
609 "varying vec3 EyeVector;\n"
611 "varying vec3 EyeVectorModelSpace;\n"
614 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
615 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
616 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
618 "#ifdef MODE_WATER\n"
619 "varying vec4 ModelViewProjectionPosition;\n"
621 "#ifdef MODE_REFRACTION\n"
622 "varying vec4 ModelViewProjectionPosition;\n"
624 "#ifdef USEREFLECTION\n"
625 "varying vec4 ModelViewProjectionPosition;\n"
632 "// vertex shader specific:\n"
633 "#ifdef VERTEX_SHADER\n"
635 "uniform vec3 LightPosition;\n"
636 "uniform vec3 EyePosition;\n"
637 "uniform vec3 LightDir;\n"
639 "// 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"
643 " gl_FrontColor = gl_Color;\n"
644 " // copy the surface texcoord\n"
645 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
646 "#ifdef USEVERTEXTEXTUREBLEND\n"
647 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
649 "#ifndef MODE_LIGHTSOURCE\n"
650 "# ifndef MODE_LIGHTDIRECTION\n"
651 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
655 "#ifdef MODE_LIGHTSOURCE\n"
656 " // transform vertex position into light attenuation/cubemap space\n"
657 " // (-1 to +1 across the light box)\n"
658 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
660 " // transform unnormalized light direction into tangent space\n"
661 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
662 " // normalize it per pixel)\n"
663 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
664 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
665 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
666 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
669 "#ifdef MODE_LIGHTDIRECTION\n"
670 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
671 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
672 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
675 " // transform unnormalized eye direction into tangent space\n"
677 " vec3 EyeVectorModelSpace;\n"
679 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
680 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
681 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
682 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
684 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
685 " VectorS = gl_MultiTexCoord1.xyz;\n"
686 " VectorT = gl_MultiTexCoord2.xyz;\n"
687 " VectorR = gl_MultiTexCoord3.xyz;\n"
690 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
691 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
692 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
693 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
696 "// transform vertex to camera space, using ftransform to match non-VS\n"
698 " gl_Position = ftransform();\n"
700 "#ifdef MODE_WATER\n"
701 " ModelViewProjectionPosition = gl_Position;\n"
703 "#ifdef MODE_REFRACTION\n"
704 " ModelViewProjectionPosition = gl_Position;\n"
706 "#ifdef USEREFLECTION\n"
707 " ModelViewProjectionPosition = gl_Position;\n"
711 "#endif // VERTEX_SHADER\n"
716 "// fragment shader specific:\n"
717 "#ifdef FRAGMENT_SHADER\n"
719 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
720 "uniform sampler2D Texture_Normal;\n"
721 "uniform sampler2D Texture_Color;\n"
722 "uniform sampler2D Texture_Gloss;\n"
723 "uniform sampler2D Texture_Glow;\n"
724 "uniform sampler2D Texture_SecondaryNormal;\n"
725 "uniform sampler2D Texture_SecondaryColor;\n"
726 "uniform sampler2D Texture_SecondaryGloss;\n"
727 "uniform sampler2D Texture_SecondaryGlow;\n"
728 "uniform sampler2D Texture_Pants;\n"
729 "uniform sampler2D Texture_Shirt;\n"
730 "uniform sampler2D Texture_FogMask;\n"
731 "uniform sampler2D Texture_Lightmap;\n"
732 "uniform sampler2D Texture_Deluxemap;\n"
733 "uniform sampler2D Texture_Refraction;\n"
734 "uniform sampler2D Texture_Reflection;\n"
735 "uniform sampler2D Texture_Attenuation;\n"
736 "uniform samplerCube Texture_Cube;\n"
738 "uniform myhalf3 LightColor;\n"
739 "uniform myhalf3 AmbientColor;\n"
740 "uniform myhalf3 DiffuseColor;\n"
741 "uniform myhalf3 SpecularColor;\n"
742 "uniform myhalf3 Color_Pants;\n"
743 "uniform myhalf3 Color_Shirt;\n"
744 "uniform myhalf3 FogColor;\n"
746 "uniform myhalf4 TintColor;\n"
749 "//#ifdef MODE_WATER\n"
750 "uniform vec4 DistortScaleRefractReflect;\n"
751 "uniform vec4 ScreenScaleRefractReflect;\n"
752 "uniform vec4 ScreenCenterRefractReflect;\n"
753 "uniform myhalf4 RefractColor;\n"
754 "uniform myhalf4 ReflectColor;\n"
755 "uniform myhalf ReflectFactor;\n"
756 "uniform myhalf ReflectOffset;\n"
758 "//# ifdef MODE_REFRACTION\n"
759 "//uniform vec4 DistortScaleRefractReflect;\n"
760 "//uniform vec4 ScreenScaleRefractReflect;\n"
761 "//uniform vec4 ScreenCenterRefractReflect;\n"
762 "//uniform myhalf4 RefractColor;\n"
763 "//# ifdef USEREFLECTION\n"
764 "//uniform myhalf4 ReflectColor;\n"
767 "//# ifdef USEREFLECTION\n"
768 "//uniform vec4 DistortScaleRefractReflect;\n"
769 "//uniform vec4 ScreenScaleRefractReflect;\n"
770 "//uniform vec4 ScreenCenterRefractReflect;\n"
771 "//uniform myhalf4 ReflectColor;\n"
776 "uniform myhalf GlowScale;\n"
777 "uniform myhalf SceneBrightness;\n"
778 "#ifdef USECONTRASTBOOST\n"
779 "uniform myhalf ContrastBoostCoeff;\n"
782 "uniform float OffsetMapping_Scale;\n"
783 "uniform float OffsetMapping_Bias;\n"
784 "uniform float FogRangeRecip;\n"
786 "uniform myhalf AmbientScale;\n"
787 "uniform myhalf DiffuseScale;\n"
788 "uniform myhalf SpecularScale;\n"
789 "uniform myhalf SpecularPower;\n"
791 "#ifdef USEOFFSETMAPPING\n"
792 "vec2 OffsetMapping(vec2 TexCoord)\n"
794 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
795 " // 14 sample relief mapping: linear search and then binary search\n"
796 " // this basically steps forward a small amount repeatedly until it finds\n"
797 " // itself inside solid, then jitters forward and back using decreasing\n"
798 " // amounts to find the impact\n"
799 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
800 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
801 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
802 " vec3 RT = vec3(TexCoord, 1);\n"
803 " OffsetVector *= 0.1;\n"
804 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
805 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
806 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
807 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
808 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
809 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
810 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
811 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
812 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
813 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
814 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
815 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
816 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
817 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
820 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
821 " // this basically moves forward the full distance, and then backs up based\n"
822 " // on height of samples\n"
823 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
824 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
825 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
826 " TexCoord += OffsetVector;\n"
827 " OffsetVector *= 0.333;\n"
828 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
829 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
830 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
831 " return TexCoord;\n"
834 "#endif // USEOFFSETMAPPING\n"
836 "#ifdef MODE_WATER\n"
841 "#ifdef USEOFFSETMAPPING\n"
842 " // apply offsetmapping\n"
843 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
844 "#define TexCoord TexCoordOffset\n"
847 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
848 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
849 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
850 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
851 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
854 "#else // !MODE_WATER\n"
855 "#ifdef MODE_REFRACTION\n"
857 "// refraction pass\n"
860 "#ifdef USEOFFSETMAPPING\n"
861 " // apply offsetmapping\n"
862 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
863 "#define TexCoord TexCoordOffset\n"
866 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
867 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
868 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
869 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
872 "#else // !MODE_REFRACTION\n"
875 "#ifdef USEOFFSETMAPPING\n"
876 " // apply offsetmapping\n"
877 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
878 "#define TexCoord TexCoordOffset\n"
881 " // combine the diffuse textures (base, pants, shirt)\n"
882 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
883 "#ifdef USECOLORMAPPING\n"
884 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
886 "#ifdef USEVERTEXTEXTUREBLEND\n"
887 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
888 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
889 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
890 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
892 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
895 "#ifdef USEDIFFUSE\n"
896 " // get the surface normal and the gloss color\n"
897 "# ifdef USEVERTEXTEXTUREBLEND\n"
898 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
899 "# ifdef USESPECULAR\n"
900 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
903 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
904 "# ifdef USESPECULAR\n"
905 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
912 "#ifdef MODE_LIGHTSOURCE\n"
915 " // calculate surface normal, light normal, and specular normal\n"
916 " // compute color intensity for the two textures (colormap and glossmap)\n"
917 " // scale by light color and attenuation as efficiently as possible\n"
918 " // (do as much scalar math as possible rather than vector math)\n"
919 "# ifdef USEDIFFUSE\n"
920 " // get the light normal\n"
921 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
923 "# ifdef USESPECULAR\n"
924 "# ifndef USEEXACTSPECULARMATH\n"
925 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
928 " // calculate directional shading\n"
929 "# ifdef USEEXACTSPECULARMATH\n"
930 " 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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
932 " 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"
935 "# ifdef USEDIFFUSE\n"
936 " // calculate directional shading\n"
937 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
939 " // calculate directionless shading\n"
940 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
944 "# ifdef USECUBEFILTER\n"
945 " // apply light cubemap filter\n"
946 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
947 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
949 "#endif // MODE_LIGHTSOURCE\n"
954 "#ifdef MODE_LIGHTDIRECTION\n"
955 " // directional model lighting\n"
956 "# ifdef USEDIFFUSE\n"
957 " // get the light normal\n"
958 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
960 "# ifdef USESPECULAR\n"
961 " // calculate directional shading\n"
962 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
963 "# ifdef USEEXACTSPECULARMATH\n"
964 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
966 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
967 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
970 "# ifdef USEDIFFUSE\n"
972 " // calculate directional shading\n"
973 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
975 " color.rgb *= AmbientColor;\n"
978 "#endif // MODE_LIGHTDIRECTION\n"
983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
984 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
986 " // get the light normal\n"
987 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
988 " myhalf3 diffusenormal;\n"
989 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
990 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
991 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
992 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
993 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
994 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
995 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
996 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
997 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
998 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
999 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1000 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1001 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1002 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1003 "# ifdef USESPECULAR\n"
1004 "# ifdef USEEXACTSPECULARMATH\n"
1005 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1007 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1008 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1012 " // apply lightmap color\n"
1013 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1014 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1019 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1020 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1022 " // get the light normal\n"
1023 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1024 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1025 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1026 "# ifdef USESPECULAR\n"
1027 "# ifdef USEEXACTSPECULARMATH\n"
1028 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1030 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1031 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1035 " // apply lightmap color\n"
1036 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1037 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1042 "#ifdef MODE_LIGHTMAP\n"
1043 " // apply lightmap color\n"
1044 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1045 "#endif // MODE_LIGHTMAP\n"
1050 "#ifdef MODE_VERTEXCOLOR\n"
1051 " // apply lightmap color\n"
1052 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1053 "#endif // MODE_VERTEXCOLOR\n"
1058 "#ifdef MODE_FLATCOLOR\n"
1059 "#endif // MODE_FLATCOLOR\n"
1067 " color *= TintColor;\n"
1070 "#ifdef USEVERTEXTEXTUREBLEND\n"
1071 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1073 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1077 "#ifdef USECONTRASTBOOST\n"
1078 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1081 " color.rgb *= SceneBrightness;\n"
1083 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1085 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1088 " // 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"
1089 "#ifdef USEREFLECTION\n"
1090 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1091 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1092 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1093 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1096 " gl_FragColor = vec4(color);\n"
1098 "#endif // !MODE_REFRACTION\n"
1099 "#endif // !MODE_WATER\n"
1101 "#endif // FRAGMENT_SHADER\n"
1103 "#endif // !MODE_GENERIC\n"
1104 "#endif // !MODE_POSTPROCESS\n"
1105 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1108 typedef struct shaderpermutationinfo_s
1110 const char *pretext;
1113 shaderpermutationinfo_t;
1115 typedef struct shadermodeinfo_s
1117 const char *vertexfilename;
1118 const char *geometryfilename;
1119 const char *fragmentfilename;
1120 const char *pretext;
1125 typedef enum shaderpermutation_e
1127 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1128 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1129 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1130 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1131 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1132 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1133 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1134 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1135 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1136 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1137 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1138 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1139 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1140 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1141 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1142 SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
1143 SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
1145 shaderpermutation_t;
1147 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1148 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1150 {"#define USEDIFFUSE\n", " diffuse"},
1151 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1152 {"#define USECOLORMAPPING\n", " colormapping"},
1153 {"#define USECONTRASTBOOST\n", " contrastboost"},
1154 {"#define USEFOG\n", " fog"},
1155 {"#define USECUBEFILTER\n", " cubefilter"},
1156 {"#define USEGLOW\n", " glow"},
1157 {"#define USESPECULAR\n", " specular"},
1158 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1159 {"#define USEREFLECTION\n", " reflection"},
1160 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1161 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1162 {"#define USEGAMMARAMPS\n", " gammaramps"},
1163 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1164 {"#define USESATURATION\n", " saturation"},
1167 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1168 typedef enum shadermode_e
1170 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1171 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1172 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1173 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1174 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1175 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1176 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1177 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1178 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1179 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1180 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1181 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1186 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1187 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1189 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1190 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1191 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1192 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1193 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1194 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1195 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1196 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1197 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1198 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1199 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1200 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1203 typedef struct r_glsl_permutation_s
1205 /// indicates if we have tried compiling this permutation already
1207 /// 0 if compilation failed
1209 /// locations of detected uniforms in program object, or -1 if not found
1210 int loc_Texture_First;
1211 int loc_Texture_Second;
1212 int loc_Texture_GammaRamps;
1213 int loc_Texture_Normal;
1214 int loc_Texture_Color;
1215 int loc_Texture_Gloss;
1216 int loc_Texture_Glow;
1217 int loc_Texture_SecondaryNormal;
1218 int loc_Texture_SecondaryColor;
1219 int loc_Texture_SecondaryGloss;
1220 int loc_Texture_SecondaryGlow;
1221 int loc_Texture_Pants;
1222 int loc_Texture_Shirt;
1223 int loc_Texture_FogMask;
1224 int loc_Texture_Lightmap;
1225 int loc_Texture_Deluxemap;
1226 int loc_Texture_Attenuation;
1227 int loc_Texture_Cube;
1228 int loc_Texture_Refraction;
1229 int loc_Texture_Reflection;
1231 int loc_LightPosition;
1232 int loc_EyePosition;
1233 int loc_Color_Pants;
1234 int loc_Color_Shirt;
1235 int loc_FogRangeRecip;
1236 int loc_AmbientScale;
1237 int loc_DiffuseScale;
1238 int loc_SpecularScale;
1239 int loc_SpecularPower;
1241 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1242 int loc_OffsetMapping_Scale;
1244 int loc_AmbientColor;
1245 int loc_DiffuseColor;
1246 int loc_SpecularColor;
1248 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1249 int loc_GammaCoeff; ///< 1 / gamma
1250 int loc_DistortScaleRefractReflect;
1251 int loc_ScreenScaleRefractReflect;
1252 int loc_ScreenCenterRefractReflect;
1253 int loc_RefractColor;
1254 int loc_ReflectColor;
1255 int loc_ReflectFactor;
1256 int loc_ReflectOffset;
1265 r_glsl_permutation_t;
1267 /// information about each possible shader permutation
1268 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1269 /// currently selected permutation
1270 r_glsl_permutation_t *r_glsl_permutation;
1272 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1275 if (!filename || !filename[0])
1277 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1280 if (printfromdisknotice)
1281 Con_DPrint("from disk... ");
1282 return shaderstring;
1284 else if (!strcmp(filename, "glsl/default.glsl"))
1286 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1287 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1289 return shaderstring;
1292 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1295 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1296 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1297 int vertstrings_count = 0;
1298 int geomstrings_count = 0;
1299 int fragstrings_count = 0;
1300 char *vertexstring, *geometrystring, *fragmentstring;
1301 const char *vertstrings_list[32+3];
1302 const char *geomstrings_list[32+3];
1303 const char *fragstrings_list[32+3];
1304 char permutationname[256];
1311 permutationname[0] = 0;
1312 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1313 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1314 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1316 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1318 // the first pretext is which type of shader to compile as
1319 // (later these will all be bound together as a program object)
1320 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1321 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1322 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1324 // the second pretext is the mode (for example a light source)
1325 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1326 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1327 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1328 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1330 // now add all the permutation pretexts
1331 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1333 if (permutation & (1<<i))
1335 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1336 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1337 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1338 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1342 // keep line numbers correct
1343 vertstrings_list[vertstrings_count++] = "\n";
1344 geomstrings_list[geomstrings_count++] = "\n";
1345 fragstrings_list[fragstrings_count++] = "\n";
1349 // now append the shader text itself
1350 vertstrings_list[vertstrings_count++] = vertexstring;
1351 geomstrings_list[geomstrings_count++] = geometrystring;
1352 fragstrings_list[fragstrings_count++] = fragmentstring;
1354 // if any sources were NULL, clear the respective list
1356 vertstrings_count = 0;
1357 if (!geometrystring)
1358 geomstrings_count = 0;
1359 if (!fragmentstring)
1360 fragstrings_count = 0;
1362 // compile the shader program
1363 if (vertstrings_count + geomstrings_count + fragstrings_count)
1364 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1368 qglUseProgramObjectARB(p->program);CHECKGLERROR
1369 // look up all the uniform variable names we care about, so we don't
1370 // have to look them up every time we set them
1371 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1372 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1373 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1374 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1375 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1376 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1377 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1378 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1379 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1380 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1381 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1382 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1383 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1384 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1385 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1386 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1387 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1388 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1389 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1390 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1391 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1392 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1393 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1394 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1395 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1396 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1397 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1398 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1399 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1400 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1401 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1402 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1403 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1404 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1405 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1406 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1407 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1408 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1409 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1410 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1411 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1412 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1413 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1414 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1415 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1416 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1417 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1418 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1419 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1420 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1421 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1422 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1423 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1424 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1425 // initialize the samplers to refer to the texture units we use
1426 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1427 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1428 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1429 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1430 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1431 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1432 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1433 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1434 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1435 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1436 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1437 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1438 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1439 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1440 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1441 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1442 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1443 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1444 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1445 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1447 if (developer.integer)
1448 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1451 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1455 Mem_Free(vertexstring);
1457 Mem_Free(geometrystring);
1459 Mem_Free(fragmentstring);
1462 void R_GLSL_Restart_f(void)
1465 unsigned int permutation;
1466 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1467 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1468 if (r_glsl_permutations[mode][permutation].program)
1469 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1470 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1473 void R_GLSL_DumpShader_f(void)
1477 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1480 Con_Printf("failed to write to glsl/default.glsl\n");
1484 FS_Print(file, "// The engine may define the following macros:\n");
1485 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1486 for (i = 0;i < SHADERMODE_COUNT;i++)
1487 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1488 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1489 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1490 FS_Print(file, "\n");
1491 FS_Print(file, builtinshaderstring);
1494 Con_Printf("glsl/default.glsl written\n");
1497 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1499 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1500 if (r_glsl_permutation != perm)
1502 r_glsl_permutation = perm;
1503 if (!r_glsl_permutation->program)
1505 if (!r_glsl_permutation->compiled)
1506 R_GLSL_CompilePermutation(mode, permutation);
1507 if (!r_glsl_permutation->program)
1509 // remove features until we find a valid permutation
1511 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1513 // reduce i more quickly whenever it would not remove any bits
1514 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1515 if (!(permutation & j))
1518 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1519 if (!r_glsl_permutation->compiled)
1520 R_GLSL_CompilePermutation(mode, permutation);
1521 if (r_glsl_permutation->program)
1524 if (i >= SHADERPERMUTATION_COUNT)
1526 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");
1527 Cvar_SetValueQuick(&r_glsl, 0);
1528 R_GLSL_Restart_f(); // unload shaders
1529 return; // no bit left to clear
1534 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1538 void R_SetupGenericShader(qboolean usetexture)
1540 if (gl_support_fragment_shader)
1542 if (r_glsl.integer && r_glsl_usegeneric.integer)
1543 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1544 else if (r_glsl_permutation)
1546 r_glsl_permutation = NULL;
1547 qglUseProgramObjectARB(0);CHECKGLERROR
1552 void R_SetupGenericTwoTextureShader(int texturemode)
1554 if (gl_support_fragment_shader)
1556 if (r_glsl.integer && r_glsl_usegeneric.integer)
1557 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1558 else if (r_glsl_permutation)
1560 r_glsl_permutation = NULL;
1561 qglUseProgramObjectARB(0);CHECKGLERROR
1564 if (!r_glsl_permutation)
1566 if (texturemode == GL_DECAL && gl_combine.integer)
1567 texturemode = GL_INTERPOLATE_ARB;
1568 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1572 void R_SetupDepthOrShadowShader(void)
1574 if (gl_support_fragment_shader)
1576 if (r_glsl.integer && r_glsl_usegeneric.integer)
1577 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1578 else if (r_glsl_permutation)
1580 r_glsl_permutation = NULL;
1581 qglUseProgramObjectARB(0);CHECKGLERROR
1586 extern rtexture_t *r_shadow_attenuationgradienttexture;
1587 extern rtexture_t *r_shadow_attenuation2dtexture;
1588 extern rtexture_t *r_shadow_attenuation3dtexture;
1589 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1591 // select a permutation of the lighting shader appropriate to this
1592 // combination of texture, entity, light source, and fogging, only use the
1593 // minimum features necessary to avoid wasting rendering time in the
1594 // fragment shader on features that are not being used
1595 unsigned int permutation = 0;
1596 unsigned int mode = 0;
1597 // TODO: implement geometry-shader based shadow volumes someday
1598 if (r_glsl_offsetmapping.integer)
1600 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1601 if (r_glsl_offsetmapping_reliefmapping.integer)
1602 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1604 if (rsurfacepass == RSURFPASS_BACKGROUND)
1606 // distorted background
1607 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1608 mode = SHADERMODE_WATER;
1610 mode = SHADERMODE_REFRACTION;
1612 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1615 mode = SHADERMODE_LIGHTSOURCE;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1617 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1618 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1619 permutation |= SHADERPERMUTATION_CUBEFILTER;
1620 if (diffusescale > 0)
1621 permutation |= SHADERPERMUTATION_DIFFUSE;
1622 if (specularscale > 0)
1623 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1624 if (r_refdef.fogenabled)
1625 permutation |= SHADERPERMUTATION_FOG;
1626 if (rsurface.texture->colormapping)
1627 permutation |= SHADERPERMUTATION_COLORMAPPING;
1628 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1629 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1631 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1633 // unshaded geometry (fullbright or ambient model lighting)
1634 mode = SHADERMODE_FLATCOLOR;
1635 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1636 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1637 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1638 permutation |= SHADERPERMUTATION_GLOW;
1639 if (r_refdef.fogenabled)
1640 permutation |= SHADERPERMUTATION_FOG;
1641 if (rsurface.texture->colormapping)
1642 permutation |= SHADERPERMUTATION_COLORMAPPING;
1643 if (r_glsl_offsetmapping.integer)
1645 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1646 if (r_glsl_offsetmapping_reliefmapping.integer)
1647 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1649 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1650 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1651 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1652 permutation |= SHADERPERMUTATION_REFLECTION;
1654 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1656 // directional model lighting
1657 mode = SHADERMODE_LIGHTDIRECTION;
1658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1659 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1660 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1661 permutation |= SHADERPERMUTATION_GLOW;
1662 permutation |= SHADERPERMUTATION_DIFFUSE;
1663 if (specularscale > 0)
1664 permutation |= SHADERPERMUTATION_SPECULAR;
1665 if (r_refdef.fogenabled)
1666 permutation |= SHADERPERMUTATION_FOG;
1667 if (rsurface.texture->colormapping)
1668 permutation |= SHADERPERMUTATION_COLORMAPPING;
1669 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1670 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1672 permutation |= SHADERPERMUTATION_REFLECTION;
1674 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1676 // ambient model lighting
1677 mode = SHADERMODE_LIGHTDIRECTION;
1678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1679 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1680 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1681 permutation |= SHADERPERMUTATION_GLOW;
1682 if (r_refdef.fogenabled)
1683 permutation |= SHADERPERMUTATION_FOG;
1684 if (rsurface.texture->colormapping)
1685 permutation |= SHADERPERMUTATION_COLORMAPPING;
1686 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1687 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1689 permutation |= SHADERPERMUTATION_REFLECTION;
1694 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1696 // deluxemapping (light direction texture)
1697 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1698 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1700 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1701 permutation |= SHADERPERMUTATION_DIFFUSE;
1702 if (specularscale > 0)
1703 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1705 else if (r_glsl_deluxemapping.integer >= 2)
1707 // fake deluxemapping (uniform light direction in tangentspace)
1708 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1709 permutation |= SHADERPERMUTATION_DIFFUSE;
1710 if (specularscale > 0)
1711 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1713 else if (rsurface.uselightmaptexture)
1715 // ordinary lightmapping (q1bsp, q3bsp)
1716 mode = SHADERMODE_LIGHTMAP;
1720 // ordinary vertex coloring (q3bsp)
1721 mode = SHADERMODE_VERTEXCOLOR;
1723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1724 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1725 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1726 permutation |= SHADERPERMUTATION_GLOW;
1727 if (r_refdef.fogenabled)
1728 permutation |= SHADERPERMUTATION_FOG;
1729 if (rsurface.texture->colormapping)
1730 permutation |= SHADERPERMUTATION_COLORMAPPING;
1731 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1732 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1733 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1734 permutation |= SHADERPERMUTATION_REFLECTION;
1736 if(permutation & SHADERPERMUTATION_SPECULAR)
1737 if(r_shadow_glossexact.integer)
1738 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1739 R_SetupShader_SetPermutation(mode, permutation);
1740 if (mode == SHADERMODE_LIGHTSOURCE)
1742 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1743 if (permutation & SHADERPERMUTATION_DIFFUSE)
1745 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1746 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1747 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1748 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1752 // ambient only is simpler
1753 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]);
1754 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1755 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1756 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1758 // additive passes are only darkened by fog, not tinted
1759 if (r_glsl_permutation->loc_FogColor >= 0)
1760 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1764 if (mode == SHADERMODE_LIGHTDIRECTION)
1766 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);
1767 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);
1768 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);
1769 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]);
1773 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1774 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1775 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1777 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]);
1778 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1779 // additive passes are only darkened by fog, not tinted
1780 if (r_glsl_permutation->loc_FogColor >= 0)
1782 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1783 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1785 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1787 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);
1788 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]);
1789 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]);
1790 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1791 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1792 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1793 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1795 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1797 // The formula used is actually:
1798 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1799 // color.rgb *= SceneBrightness;
1801 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1802 // and do [[calculations]] here in the engine
1803 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1804 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1807 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1808 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1809 if (r_glsl_permutation->loc_Color_Pants >= 0)
1811 if (rsurface.texture->currentskinframe->pants)
1812 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1814 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1816 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1818 if (rsurface.texture->currentskinframe->shirt)
1819 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1821 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1823 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1824 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1826 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1830 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1832 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1836 #define SKINFRAME_HASH 1024
1840 int loadsequence; // incremented each level change
1841 memexpandablearray_t array;
1842 skinframe_t *hash[SKINFRAME_HASH];
1845 r_skinframe_t r_skinframe;
1847 void R_SkinFrame_PrepareForPurge(void)
1849 r_skinframe.loadsequence++;
1850 // wrap it without hitting zero
1851 if (r_skinframe.loadsequence >= 200)
1852 r_skinframe.loadsequence = 1;
1855 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1859 // mark the skinframe as used for the purging code
1860 skinframe->loadsequence = r_skinframe.loadsequence;
1863 void R_SkinFrame_Purge(void)
1867 for (i = 0;i < SKINFRAME_HASH;i++)
1869 for (s = r_skinframe.hash[i];s;s = s->next)
1871 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1873 if (s->merged == s->base)
1875 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1876 R_PurgeTexture(s->stain );s->stain = NULL;
1877 R_PurgeTexture(s->merged);s->merged = NULL;
1878 R_PurgeTexture(s->base );s->base = NULL;
1879 R_PurgeTexture(s->pants );s->pants = NULL;
1880 R_PurgeTexture(s->shirt );s->shirt = NULL;
1881 R_PurgeTexture(s->nmap );s->nmap = NULL;
1882 R_PurgeTexture(s->gloss );s->gloss = NULL;
1883 R_PurgeTexture(s->glow );s->glow = NULL;
1884 R_PurgeTexture(s->fog );s->fog = NULL;
1885 s->loadsequence = 0;
1891 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1893 char basename[MAX_QPATH];
1895 Image_StripImageExtension(name, basename, sizeof(basename));
1897 if( last == NULL ) {
1899 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1900 item = r_skinframe.hash[hashindex];
1905 // linearly search through the hash bucket
1906 for( ; item ; item = item->next ) {
1907 if( !strcmp( item->basename, basename ) ) {
1914 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1918 char basename[MAX_QPATH];
1920 Image_StripImageExtension(name, basename, sizeof(basename));
1922 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1923 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1924 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1928 rtexture_t *dyntexture;
1929 // check whether its a dynamic texture
1930 dyntexture = CL_GetDynTexture( basename );
1931 if (!add && !dyntexture)
1933 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1934 memset(item, 0, sizeof(*item));
1935 strlcpy(item->basename, basename, sizeof(item->basename));
1936 item->base = dyntexture; // either NULL or dyntexture handle
1937 item->textureflags = textureflags;
1938 item->comparewidth = comparewidth;
1939 item->compareheight = compareheight;
1940 item->comparecrc = comparecrc;
1941 item->next = r_skinframe.hash[hashindex];
1942 r_skinframe.hash[hashindex] = item;
1944 else if( item->base == NULL )
1946 rtexture_t *dyntexture;
1947 // check whether its a dynamic texture
1948 // 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]
1949 dyntexture = CL_GetDynTexture( basename );
1950 item->base = dyntexture; // either NULL or dyntexture handle
1953 R_SkinFrame_MarkUsed(item);
1957 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1959 unsigned long long avgcolor[5], wsum; \
1967 for(pix = 0; pix < cnt; ++pix) \
1970 for(comp = 0; comp < 3; ++comp) \
1972 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1975 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1977 for(comp = 0; comp < 3; ++comp) \
1978 avgcolor[comp] += getpixel * w; \
1981 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1982 avgcolor[4] += getpixel; \
1984 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1986 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1987 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1988 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1989 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1992 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1994 // FIXME: it should be possible to disable loading various layers using
1995 // cvars, to prevent wasted loading time and memory usage if the user does
1997 qboolean loadnormalmap = true;
1998 qboolean loadgloss = true;
1999 qboolean loadpantsandshirt = true;
2000 qboolean loadglow = true;
2002 unsigned char *pixels;
2003 unsigned char *bumppixels;
2004 unsigned char *basepixels = NULL;
2005 int basepixels_width;
2006 int basepixels_height;
2007 skinframe_t *skinframe;
2011 if (cls.state == ca_dedicated)
2014 // return an existing skinframe if already loaded
2015 // if loading of the first image fails, don't make a new skinframe as it
2016 // would cause all future lookups of this to be missing
2017 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2018 if (skinframe && skinframe->base)
2021 basepixels = loadimagepixelsbgra(name, complain, true);
2022 if (basepixels == NULL)
2025 if (developer_loading.integer)
2026 Con_Printf("loading skin \"%s\"\n", name);
2028 // we've got some pixels to store, so really allocate this new texture now
2030 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2031 skinframe->stain = NULL;
2032 skinframe->merged = NULL;
2033 skinframe->base = r_texture_notexture;
2034 skinframe->pants = NULL;
2035 skinframe->shirt = NULL;
2036 skinframe->nmap = r_texture_blanknormalmap;
2037 skinframe->gloss = NULL;
2038 skinframe->glow = NULL;
2039 skinframe->fog = NULL;
2041 basepixels_width = image_width;
2042 basepixels_height = image_height;
2043 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);
2045 if (textureflags & TEXF_ALPHA)
2047 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2048 if (basepixels[j] < 255)
2050 if (j < basepixels_width * basepixels_height * 4)
2052 // has transparent pixels
2054 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2055 for (j = 0;j < image_width * image_height * 4;j += 4)
2060 pixels[j+3] = basepixels[j+3];
2062 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);
2067 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2068 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2070 // _norm is the name used by tenebrae and has been adopted as standard
2073 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2075 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2079 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2081 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2082 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2083 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2085 Mem_Free(bumppixels);
2087 else if (r_shadow_bumpscale_basetexture.value > 0)
2089 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2090 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2091 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2095 // _luma is supported for tenebrae compatibility
2096 // (I think it's a very stupid name, but oh well)
2097 // _glow is the preferred name
2098 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;}
2099 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;}
2100 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;}
2101 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;}
2104 Mem_Free(basepixels);
2109 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2112 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2115 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)
2120 for (i = 0;i < width*height;i++)
2121 if (((unsigned char *)&palette[in[i]])[3] > 0)
2123 if (i == width*height)
2126 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2129 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2130 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2133 unsigned char *temp1, *temp2;
2134 skinframe_t *skinframe;
2136 if (cls.state == ca_dedicated)
2139 // if already loaded just return it, otherwise make a new skinframe
2140 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2141 if (skinframe && skinframe->base)
2144 skinframe->stain = NULL;
2145 skinframe->merged = NULL;
2146 skinframe->base = r_texture_notexture;
2147 skinframe->pants = NULL;
2148 skinframe->shirt = NULL;
2149 skinframe->nmap = r_texture_blanknormalmap;
2150 skinframe->gloss = NULL;
2151 skinframe->glow = NULL;
2152 skinframe->fog = NULL;
2154 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2158 if (developer_loading.integer)
2159 Con_Printf("loading 32bit skin \"%s\"\n", name);
2161 if (r_shadow_bumpscale_basetexture.value > 0)
2163 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2164 temp2 = temp1 + width * height * 4;
2165 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2166 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2169 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2170 if (textureflags & TEXF_ALPHA)
2172 for (i = 3;i < width * height * 4;i += 4)
2173 if (skindata[i] < 255)
2175 if (i < width * height * 4)
2177 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2178 memcpy(fogpixels, skindata, width * height * 4);
2179 for (i = 0;i < width * height * 4;i += 4)
2180 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2181 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2182 Mem_Free(fogpixels);
2186 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2187 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2192 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2195 unsigned char *temp1, *temp2;
2196 unsigned int *palette;
2197 skinframe_t *skinframe;
2199 if (cls.state == ca_dedicated)
2202 // if already loaded just return it, otherwise make a new skinframe
2203 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2204 if (skinframe && skinframe->base)
2207 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2209 skinframe->stain = NULL;
2210 skinframe->merged = NULL;
2211 skinframe->base = r_texture_notexture;
2212 skinframe->pants = NULL;
2213 skinframe->shirt = NULL;
2214 skinframe->nmap = r_texture_blanknormalmap;
2215 skinframe->gloss = NULL;
2216 skinframe->glow = NULL;
2217 skinframe->fog = NULL;
2219 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2223 if (developer_loading.integer)
2224 Con_Printf("loading quake skin \"%s\"\n", name);
2226 if (r_shadow_bumpscale_basetexture.value > 0)
2228 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2229 temp2 = temp1 + width * height * 4;
2230 // use either a custom palette or the quake palette
2231 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2232 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2233 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2236 // use either a custom palette, or the quake palette
2237 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2238 if (loadglowtexture)
2239 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2240 if (loadpantsandshirt)
2242 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2243 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2245 if (skinframe->pants || skinframe->shirt)
2246 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
2247 if (textureflags & TEXF_ALPHA)
2249 for (i = 0;i < width * height;i++)
2250 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2252 if (i < width * height)
2253 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2256 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2257 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2262 skinframe_t *R_SkinFrame_LoadMissing(void)
2264 skinframe_t *skinframe;
2266 if (cls.state == ca_dedicated)
2269 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2270 skinframe->stain = NULL;
2271 skinframe->merged = NULL;
2272 skinframe->base = r_texture_notexture;
2273 skinframe->pants = NULL;
2274 skinframe->shirt = NULL;
2275 skinframe->nmap = r_texture_blanknormalmap;
2276 skinframe->gloss = NULL;
2277 skinframe->glow = NULL;
2278 skinframe->fog = NULL;
2280 skinframe->avgcolor[0] = rand() / RAND_MAX;
2281 skinframe->avgcolor[1] = rand() / RAND_MAX;
2282 skinframe->avgcolor[2] = rand() / RAND_MAX;
2283 skinframe->avgcolor[3] = 1;
2288 void gl_main_start(void)
2292 memset(r_queries, 0, sizeof(r_queries));
2294 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2295 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2297 // set up r_skinframe loading system for textures
2298 memset(&r_skinframe, 0, sizeof(r_skinframe));
2299 r_skinframe.loadsequence = 1;
2300 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2302 r_main_texturepool = R_AllocTexturePool();
2303 R_BuildBlankTextures();
2305 if (gl_texturecubemap)
2308 R_BuildNormalizationCube();
2310 r_texture_fogattenuation = NULL;
2311 r_texture_gammaramps = NULL;
2312 //r_texture_fogintensity = NULL;
2313 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2314 memset(&r_waterstate, 0, sizeof(r_waterstate));
2315 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2316 memset(&r_svbsp, 0, sizeof (r_svbsp));
2318 r_refdef.fogmasktable_density = 0;
2321 extern rtexture_t *loadingscreentexture;
2322 void gl_main_shutdown(void)
2325 qglDeleteQueriesARB(r_maxqueries, r_queries);
2329 memset(r_queries, 0, sizeof(r_queries));
2331 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2332 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2334 // clear out the r_skinframe state
2335 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2336 memset(&r_skinframe, 0, sizeof(r_skinframe));
2339 Mem_Free(r_svbsp.nodes);
2340 memset(&r_svbsp, 0, sizeof (r_svbsp));
2341 R_FreeTexturePool(&r_main_texturepool);
2342 loadingscreentexture = NULL;
2343 r_texture_blanknormalmap = NULL;
2344 r_texture_white = NULL;
2345 r_texture_grey128 = NULL;
2346 r_texture_black = NULL;
2347 r_texture_whitecube = NULL;
2348 r_texture_normalizationcube = NULL;
2349 r_texture_fogattenuation = NULL;
2350 r_texture_gammaramps = NULL;
2351 //r_texture_fogintensity = NULL;
2352 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2353 memset(&r_waterstate, 0, sizeof(r_waterstate));
2357 extern void CL_ParseEntityLump(char *entitystring);
2358 void gl_main_newmap(void)
2360 // FIXME: move this code to client
2362 char *entities, entname[MAX_QPATH];
2365 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2366 l = (int)strlen(entname) - 4;
2367 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2369 memcpy(entname + l, ".ent", 5);
2370 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2372 CL_ParseEntityLump(entities);
2377 if (cl.worldmodel->brush.entities)
2378 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2382 void GL_Main_Init(void)
2384 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2386 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2387 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2388 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2389 if (gamemode == GAME_NEHAHRA)
2391 Cvar_RegisterVariable (&gl_fogenable);
2392 Cvar_RegisterVariable (&gl_fogdensity);
2393 Cvar_RegisterVariable (&gl_fogred);
2394 Cvar_RegisterVariable (&gl_foggreen);
2395 Cvar_RegisterVariable (&gl_fogblue);
2396 Cvar_RegisterVariable (&gl_fogstart);
2397 Cvar_RegisterVariable (&gl_fogend);
2398 Cvar_RegisterVariable (&gl_skyclip);
2400 Cvar_RegisterVariable(&r_motionblur);
2401 Cvar_RegisterVariable(&r_motionblur_maxblur);
2402 Cvar_RegisterVariable(&r_motionblur_bmin);
2403 Cvar_RegisterVariable(&r_motionblur_vmin);
2404 Cvar_RegisterVariable(&r_motionblur_vmax);
2405 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2406 Cvar_RegisterVariable(&r_motionblur_randomize);
2407 Cvar_RegisterVariable(&r_damageblur);
2408 Cvar_RegisterVariable(&r_motionblur_debug);
2409 Cvar_RegisterVariable(&r_depthfirst);
2410 Cvar_RegisterVariable(&r_useinfinitefarclip);
2411 Cvar_RegisterVariable(&r_nearclip);
2412 Cvar_RegisterVariable(&r_showbboxes);
2413 Cvar_RegisterVariable(&r_showsurfaces);
2414 Cvar_RegisterVariable(&r_showtris);
2415 Cvar_RegisterVariable(&r_shownormals);
2416 Cvar_RegisterVariable(&r_showlighting);
2417 Cvar_RegisterVariable(&r_showshadowvolumes);
2418 Cvar_RegisterVariable(&r_showcollisionbrushes);
2419 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2420 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2421 Cvar_RegisterVariable(&r_showdisabledepthtest);
2422 Cvar_RegisterVariable(&r_drawportals);
2423 Cvar_RegisterVariable(&r_drawentities);
2424 Cvar_RegisterVariable(&r_cullentities_trace);
2425 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2426 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2427 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2428 Cvar_RegisterVariable(&r_drawviewmodel);
2429 Cvar_RegisterVariable(&r_speeds);
2430 Cvar_RegisterVariable(&r_fullbrights);
2431 Cvar_RegisterVariable(&r_wateralpha);
2432 Cvar_RegisterVariable(&r_dynamic);
2433 Cvar_RegisterVariable(&r_fullbright);
2434 Cvar_RegisterVariable(&r_shadows);
2435 Cvar_RegisterVariable(&r_shadows_throwdistance);
2436 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2437 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2438 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2439 Cvar_RegisterVariable(&r_fog_exp2);
2440 Cvar_RegisterVariable(&r_drawfog);
2441 Cvar_RegisterVariable(&r_textureunits);
2442 Cvar_RegisterVariable(&r_glsl);
2443 Cvar_RegisterVariable(&r_glsl_contrastboost);
2444 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2445 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2446 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2447 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2448 Cvar_RegisterVariable(&r_glsl_postprocess);
2449 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2450 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2451 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2452 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2453 Cvar_RegisterVariable(&r_glsl_usegeneric);
2454 Cvar_RegisterVariable(&r_water);
2455 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2456 Cvar_RegisterVariable(&r_water_clippingplanebias);
2457 Cvar_RegisterVariable(&r_water_refractdistort);
2458 Cvar_RegisterVariable(&r_water_reflectdistort);
2459 Cvar_RegisterVariable(&r_lerpsprites);
2460 Cvar_RegisterVariable(&r_lerpmodels);
2461 Cvar_RegisterVariable(&r_lerplightstyles);
2462 Cvar_RegisterVariable(&r_waterscroll);
2463 Cvar_RegisterVariable(&r_bloom);
2464 Cvar_RegisterVariable(&r_bloom_colorscale);
2465 Cvar_RegisterVariable(&r_bloom_brighten);
2466 Cvar_RegisterVariable(&r_bloom_blur);
2467 Cvar_RegisterVariable(&r_bloom_resolution);
2468 Cvar_RegisterVariable(&r_bloom_colorexponent);
2469 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2470 Cvar_RegisterVariable(&r_hdr);
2471 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2472 Cvar_RegisterVariable(&r_hdr_glowintensity);
2473 Cvar_RegisterVariable(&r_hdr_range);
2474 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2475 Cvar_RegisterVariable(&developer_texturelogging);
2476 Cvar_RegisterVariable(&gl_lightmaps);
2477 Cvar_RegisterVariable(&r_test);
2478 Cvar_RegisterVariable(&r_batchmode);
2479 Cvar_RegisterVariable(&r_glsl_saturation);
2480 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2481 Cvar_SetValue("r_fullbrights", 0);
2482 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2484 Cvar_RegisterVariable(&r_track_sprites);
2485 Cvar_RegisterVariable(&r_track_sprites_flags);
2486 Cvar_RegisterVariable(&r_track_sprites_scalew);
2487 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2490 extern void R_Textures_Init(void);
2491 extern void GL_Draw_Init(void);
2492 extern void GL_Main_Init(void);
2493 extern void R_Shadow_Init(void);
2494 extern void R_Sky_Init(void);
2495 extern void GL_Surf_Init(void);
2496 extern void R_Particles_Init(void);
2497 extern void R_Explosion_Init(void);
2498 extern void gl_backend_init(void);
2499 extern void Sbar_Init(void);
2500 extern void R_LightningBeams_Init(void);
2501 extern void Mod_RenderInit(void);
2503 void Render_Init(void)
2515 R_LightningBeams_Init();
2524 extern char *ENGINE_EXTENSIONS;
2527 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2528 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2529 gl_version = (const char *)qglGetString(GL_VERSION);
2530 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2534 if (!gl_platformextensions)
2535 gl_platformextensions = "";
2537 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2538 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2539 Con_Printf("GL_VERSION: %s\n", gl_version);
2540 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2541 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2543 VID_CheckExtensions();
2545 // LordHavoc: report supported extensions
2546 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2548 // clear to black (loading plaque will be seen over this)
2550 qglClearColor(0,0,0,1);CHECKGLERROR
2551 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2554 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2558 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2560 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2563 p = r_refdef.view.frustum + i;
2568 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2572 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2576 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2580 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2604 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2608 for (i = 0;i < numplanes;i++)
2615 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2619 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2623 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2627 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2631 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2635 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2639 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2643 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2651 //==================================================================================
2653 static void R_View_UpdateEntityLighting (void)
2656 entity_render_t *ent;
2657 vec3_t tempdiffusenormal;
2659 for (i = 0;i < r_refdef.scene.numentities;i++)
2661 ent = r_refdef.scene.entities[i];
2663 // skip unseen models
2664 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2668 if (ent->model && ent->model->brush.num_leafs)
2670 // TODO: use modellight for r_ambient settings on world?
2671 VectorSet(ent->modellight_ambient, 0, 0, 0);
2672 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2673 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2677 // fetch the lighting from the worldmodel data
2678 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
2679 VectorClear(ent->modellight_diffuse);
2680 VectorClear(tempdiffusenormal);
2681 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2684 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2685 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2688 VectorSet(ent->modellight_ambient, 1, 1, 1);
2690 // move the light direction into modelspace coordinates for lighting code
2691 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2692 if(VectorLength2(ent->modellight_lightdir) == 0)
2693 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2694 VectorNormalize(ent->modellight_lightdir);
2698 static void R_View_UpdateEntityVisible (void)
2701 entity_render_t *ent;
2703 if (!r_drawentities.integer)
2706 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2707 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2709 // worldmodel can check visibility
2710 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2711 for (i = 0;i < r_refdef.scene.numentities;i++)
2713 ent = r_refdef.scene.entities[i];
2714 if (!(ent->flags & renderimask))
2715 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
2716 if ((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))
2717 r_refdef.viewcache.entityvisible[i] = true;
2719 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2721 for (i = 0;i < r_refdef.scene.numentities;i++)
2723 ent = r_refdef.scene.entities[i];
2724 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2726 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))
2727 ent->last_trace_visibility = realtime;
2728 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2729 r_refdef.viewcache.entityvisible[i] = 0;
2736 // no worldmodel or it can't check visibility
2737 for (i = 0;i < r_refdef.scene.numentities;i++)
2739 ent = r_refdef.scene.entities[i];
2740 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));
2745 /// only used if skyrendermasked, and normally returns false
2746 int R_DrawBrushModelsSky (void)
2749 entity_render_t *ent;
2751 if (!r_drawentities.integer)
2755 for (i = 0;i < r_refdef.scene.numentities;i++)
2757 if (!r_refdef.viewcache.entityvisible[i])
2759 ent = r_refdef.scene.entities[i];
2760 if (!ent->model || !ent->model->DrawSky)
2762 ent->model->DrawSky(ent);
2768 static void R_DrawNoModel(entity_render_t *ent);
2769 static void R_DrawModels(void)
2772 entity_render_t *ent;
2774 if (!r_drawentities.integer)
2777 for (i = 0;i < r_refdef.scene.numentities;i++)
2779 if (!r_refdef.viewcache.entityvisible[i])
2781 ent = r_refdef.scene.entities[i];
2782 r_refdef.stats.entities++;
2783 if (ent->model && ent->model->Draw != NULL)
2784 ent->model->Draw(ent);
2790 static void R_DrawModelsDepth(void)
2793 entity_render_t *ent;
2795 if (!r_drawentities.integer)
2798 for (i = 0;i < r_refdef.scene.numentities;i++)
2800 if (!r_refdef.viewcache.entityvisible[i])
2802 ent = r_refdef.scene.entities[i];
2803 if (ent->model && ent->model->DrawDepth != NULL)
2804 ent->model->DrawDepth(ent);
2808 static void R_DrawModelsDebug(void)
2811 entity_render_t *ent;
2813 if (!r_drawentities.integer)
2816 for (i = 0;i < r_refdef.scene.numentities;i++)
2818 if (!r_refdef.viewcache.entityvisible[i])
2820 ent = r_refdef.scene.entities[i];
2821 if (ent->model && ent->model->DrawDebug != NULL)
2822 ent->model->DrawDebug(ent);
2826 static void R_DrawModelsAddWaterPlanes(void)
2829 entity_render_t *ent;
2831 if (!r_drawentities.integer)
2834 for (i = 0;i < r_refdef.scene.numentities;i++)
2836 if (!r_refdef.viewcache.entityvisible[i])
2838 ent = r_refdef.scene.entities[i];
2839 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2840 ent->model->DrawAddWaterPlanes(ent);
2844 static void R_View_SetFrustum(void)
2847 double slopex, slopey;
2848 vec3_t forward, left, up, origin;
2850 // we can't trust r_refdef.view.forward and friends in reflected scenes
2851 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2854 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2855 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2856 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2857 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2858 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2859 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2860 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2861 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2862 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2863 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2864 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2865 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2869 zNear = r_refdef.nearclip;
2870 nudge = 1.0 - 1.0 / (1<<23);
2871 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2872 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2873 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2874 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2875 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2876 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2877 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2878 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2884 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2885 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2886 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2887 r_refdef.view.frustum[0].dist = m[15] - m[12];
2889 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2890 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2891 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2892 r_refdef.view.frustum[1].dist = m[15] + m[12];
2894 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2895 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2896 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2897 r_refdef.view.frustum[2].dist = m[15] - m[13];
2899 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2900 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2901 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2902 r_refdef.view.frustum[3].dist = m[15] + m[13];
2904 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2905 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2906 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2907 r_refdef.view.frustum[4].dist = m[15] - m[14];
2909 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2910 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2911 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2912 r_refdef.view.frustum[5].dist = m[15] + m[14];
2915 if (r_refdef.view.useperspective)
2917 slopex = 1.0 / r_refdef.view.frustum_x;
2918 slopey = 1.0 / r_refdef.view.frustum_y;
2919 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2920 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2921 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2922 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2923 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2925 // Leaving those out was a mistake, those were in the old code, and they
2926 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2927 // I couldn't reproduce it after adding those normalizations. --blub
2928 VectorNormalize(r_refdef.view.frustum[0].normal);
2929 VectorNormalize(r_refdef.view.frustum[1].normal);
2930 VectorNormalize(r_refdef.view.frustum[2].normal);
2931 VectorNormalize(r_refdef.view.frustum[3].normal);
2933 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2934 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2935 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2936 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2937 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2939 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2940 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2941 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2942 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2943 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2947 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2948 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2949 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2950 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2951 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2952 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2953 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2954 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2955 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2956 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2958 r_refdef.view.numfrustumplanes = 5;
2960 if (r_refdef.view.useclipplane)
2962 r_refdef.view.numfrustumplanes = 6;
2963 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2966 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2967 PlaneClassify(r_refdef.view.frustum + i);
2969 // LordHavoc: note to all quake engine coders, Quake had a special case
2970 // for 90 degrees which assumed a square view (wrong), so I removed it,
2971 // Quake2 has it disabled as well.
2973 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2974 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2975 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2976 //PlaneClassify(&frustum[0]);
2978 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2979 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2980 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2981 //PlaneClassify(&frustum[1]);
2983 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2984 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2985 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2986 //PlaneClassify(&frustum[2]);
2988 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2989 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2990 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2991 //PlaneClassify(&frustum[3]);
2994 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2995 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2996 //PlaneClassify(&frustum[4]);
2999 void R_View_Update(void)
3001 R_View_SetFrustum();
3002 R_View_WorldVisibility(r_refdef.view.useclipplane);
3003 R_View_UpdateEntityVisible();
3004 R_View_UpdateEntityLighting();
3007 void R_SetupView(qboolean allowwaterclippingplane)
3009 if (!r_refdef.view.useperspective)
3010 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);
3011 else if (gl_stencil && r_useinfinitefarclip.integer)
3012 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3014 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3016 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3018 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3020 // LordHavoc: couldn't figure out how to make this approach the
3021 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3022 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3023 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3024 dist = r_refdef.view.clipplane.dist;
3025 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3029 void R_ResetViewRendering2D(void)
3033 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3034 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3035 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3036 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3037 GL_Color(1, 1, 1, 1);
3038 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3039 GL_BlendFunc(GL_ONE, GL_ZERO);
3040 GL_AlphaTest(false);
3041 GL_ScissorTest(false);
3042 GL_DepthMask(false);
3043 GL_DepthRange(0, 1);
3044 GL_DepthTest(false);
3045 R_Mesh_Matrix(&identitymatrix);
3046 R_Mesh_ResetTextureState();
3047 GL_PolygonOffset(0, 0);
3048 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3049 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3050 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3051 qglStencilMask(~0);CHECKGLERROR
3052 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3053 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3054 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3055 R_SetupGenericShader(true);
3058 void R_ResetViewRendering3D(void)
3062 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3063 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3065 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3066 GL_Color(1, 1, 1, 1);
3067 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3068 GL_BlendFunc(GL_ONE, GL_ZERO);
3069 GL_AlphaTest(false);
3070 GL_ScissorTest(true);
3072 GL_DepthRange(0, 1);
3074 R_Mesh_Matrix(&identitymatrix);
3075 R_Mesh_ResetTextureState();
3076 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3077 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3078 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3079 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3080 qglStencilMask(~0);CHECKGLERROR
3081 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3082 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3083 GL_CullFace(r_refdef.view.cullface_back);
3084 R_SetupGenericShader(true);
3087 void R_RenderScene(void);
3088 void R_RenderWaterPlanes(void);
3090 static void R_Water_StartFrame(void)
3093 int waterwidth, waterheight, texturewidth, textureheight;
3094 r_waterstate_waterplane_t *p;
3096 // set waterwidth and waterheight to the water resolution that will be
3097 // used (often less than the screen resolution for faster rendering)
3098 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3099 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3101 // calculate desired texture sizes
3102 // can't use water if the card does not support the texture size
3103 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3104 texturewidth = textureheight = waterwidth = waterheight = 0;
3105 else if (gl_support_arb_texture_non_power_of_two)
3107 texturewidth = waterwidth;
3108 textureheight = waterheight;
3112 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3113 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3116 // allocate textures as needed
3117 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3119 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3120 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3122 if (p->texture_refraction)
3123 R_FreeTexture(p->texture_refraction);
3124 p->texture_refraction = NULL;
3125 if (p->texture_reflection)
3126 R_FreeTexture(p->texture_reflection);
3127 p->texture_reflection = NULL;
3129 memset(&r_waterstate, 0, sizeof(r_waterstate));
3130 r_waterstate.waterwidth = waterwidth;
3131 r_waterstate.waterheight = waterheight;
3132 r_waterstate.texturewidth = texturewidth;
3133 r_waterstate.textureheight = textureheight;
3136 if (r_waterstate.waterwidth)
3138 r_waterstate.enabled = true;
3140 // set up variables that will be used in shader setup
3141 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3142 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3143 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3144 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3147 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3148 r_waterstate.numwaterplanes = 0;
3151 void R_Water_AddWaterPlane(msurface_t *surface)
3153 int triangleindex, planeindex;
3159 r_waterstate_waterplane_t *p;
3160 texture_t *t = R_GetCurrentTexture(surface->texture);
3161 // just use the first triangle with a valid normal for any decisions
3162 VectorClear(normal);
3163 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3165 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3166 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3167 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3168 TriangleNormal(vert[0], vert[1], vert[2], normal);
3169 if (VectorLength2(normal) >= 0.001)
3173 VectorCopy(normal, plane.normal);
3174 VectorNormalize(plane.normal);
3175 plane.dist = DotProduct(vert[0], plane.normal);
3176 PlaneClassify(&plane);
3177 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3179 // skip backfaces (except if nocullface is set)
3180 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3182 VectorNegate(plane.normal, plane.normal);
3184 PlaneClassify(&plane);
3188 // find a matching plane if there is one
3189 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3190 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3192 if (planeindex >= r_waterstate.maxwaterplanes)
3193 return; // nothing we can do, out of planes
3195 // if this triangle does not fit any known plane rendered this frame, add one
3196 if (planeindex >= r_waterstate.numwaterplanes)
3198 // store the new plane
3199 r_waterstate.numwaterplanes++;
3201 // clear materialflags and pvs
3202 p->materialflags = 0;
3203 p->pvsvalid = false;
3205 // merge this surface's materialflags into the waterplane
3206 p->materialflags |= t->currentmaterialflags;
3207 // merge this surface's PVS into the waterplane
3208 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3209 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3210 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3212 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3217 static void R_Water_ProcessPlanes(void)
3219 r_refdef_view_t originalview;
3220 r_refdef_view_t myview;
3222 r_waterstate_waterplane_t *p;
3224 originalview = r_refdef.view;
3226 // make sure enough textures are allocated
3227 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3229 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3231 if (!p->texture_refraction)
3232 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);
3233 if (!p->texture_refraction)
3237 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3239 if (!p->texture_reflection)
3240 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);
3241 if (!p->texture_reflection)
3247 r_refdef.view = originalview;
3248 r_refdef.view.showdebug = false;
3249 r_refdef.view.width = r_waterstate.waterwidth;
3250 r_refdef.view.height = r_waterstate.waterheight;
3251 r_refdef.view.useclipplane = true;
3252 myview = r_refdef.view;
3253 r_waterstate.renderingscene = true;
3254 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3256 // render the normal view scene and copy into texture
3257 // (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)
3258 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3260 r_refdef.view = myview;
3261 r_refdef.view.clipplane = p->plane;
3262 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3263 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3264 PlaneClassify(&r_refdef.view.clipplane);
3266 R_ResetViewRendering3D();
3267 R_ClearScreen(r_refdef.fogenabled);
3271 // copy view into the screen texture
3272 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3273 GL_ActiveTexture(0);
3275 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
3278 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3280 r_refdef.view = myview;
3281 // render reflected scene and copy into texture
3282 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3283 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3284 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3285 r_refdef.view.clipplane = p->plane;
3286 // reverse the cullface settings for this render
3287 r_refdef.view.cullface_front = GL_FRONT;
3288 r_refdef.view.cullface_back = GL_BACK;
3289 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3291 r_refdef.view.usecustompvs = true;
3293 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3295 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3298 R_ResetViewRendering3D();
3299 R_ClearScreen(r_refdef.fogenabled);
3303 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3304 GL_ActiveTexture(0);
3306 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
3309 r_waterstate.renderingscene = false;
3310 r_refdef.view = originalview;
3311 R_ResetViewRendering3D();
3312 R_ClearScreen(r_refdef.fogenabled);
3316 r_refdef.view = originalview;
3317 r_waterstate.renderingscene = false;
3318 Cvar_SetValueQuick(&r_water, 0);
3319 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3323 void R_Bloom_StartFrame(void)
3325 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3327 // set bloomwidth and bloomheight to the bloom resolution that will be
3328 // used (often less than the screen resolution for faster rendering)
3329 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3330 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3331 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3332 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3333 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3335 // calculate desired texture sizes
3336 if (gl_support_arb_texture_non_power_of_two)
3338 screentexturewidth = r_refdef.view.width;
3339 screentextureheight = r_refdef.view.height;
3340 bloomtexturewidth = r_bloomstate.bloomwidth;
3341 bloomtextureheight = r_bloomstate.bloomheight;
3345 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3346 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3347 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3348 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3351 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((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))
3353 Cvar_SetValueQuick(&r_hdr, 0);
3354 Cvar_SetValueQuick(&r_bloom, 0);
3355 Cvar_SetValueQuick(&r_motionblur, 0);
3356 Cvar_SetValueQuick(&r_damageblur, 0);
3359 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3360 screentexturewidth = screentextureheight = 0;
3361 if (!r_hdr.integer && !r_bloom.integer)
3362 bloomtexturewidth = bloomtextureheight = 0;
3364 // allocate textures as needed
3365 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3367 if (r_bloomstate.texture_screen)
3368 R_FreeTexture(r_bloomstate.texture_screen);
3369 r_bloomstate.texture_screen = NULL;
3370 r_bloomstate.screentexturewidth = screentexturewidth;
3371 r_bloomstate.screentextureheight = screentextureheight;
3372 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3373 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);
3375 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3377 if (r_bloomstate.texture_bloom)
3378 R_FreeTexture(r_bloomstate.texture_bloom);
3379 r_bloomstate.texture_bloom = NULL;
3380 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3381 r_bloomstate.bloomtextureheight = bloomtextureheight;
3382 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3383 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);
3386 // set up a texcoord array for the full resolution screen image
3387 // (we have to keep this around to copy back during final render)
3388 r_bloomstate.screentexcoord2f[0] = 0;
3389 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3390 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3391 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3392 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3393 r_bloomstate.screentexcoord2f[5] = 0;
3394 r_bloomstate.screentexcoord2f[6] = 0;
3395 r_bloomstate.screentexcoord2f[7] = 0;
3397 // set up a texcoord array for the reduced resolution bloom image
3398 // (which will be additive blended over the screen image)
3399 r_bloomstate.bloomtexcoord2f[0] = 0;
3400 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3401 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3402 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3403 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3404 r_bloomstate.bloomtexcoord2f[5] = 0;
3405 r_bloomstate.bloomtexcoord2f[6] = 0;
3406 r_bloomstate.bloomtexcoord2f[7] = 0;
3408 if (r_hdr.integer || r_bloom.integer)
3410 r_bloomstate.enabled = true;
3411 r_bloomstate.hdr = r_hdr.integer != 0;
3415 void R_Bloom_CopyBloomTexture(float colorscale)
3417 r_refdef.stats.bloom++;
3419 // scale down screen texture to the bloom texture size
3421 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3422 GL_BlendFunc(GL_ONE, GL_ZERO);
3423 GL_Color(colorscale, colorscale, colorscale, 1);
3424 // TODO: optimize with multitexture or GLSL
3425 R_SetupGenericShader(true);
3426 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3427 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3428 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3429 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3431 // we now have a bloom image in the framebuffer
3432 // copy it into the bloom image texture for later processing
3433 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3434 GL_ActiveTexture(0);
3436 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
3437 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3440 void R_Bloom_CopyHDRTexture(void)
3442 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3443 GL_ActiveTexture(0);
3445 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
3446 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3449 void R_Bloom_MakeTexture(void)
3452 float xoffset, yoffset, r, brighten;
3454 r_refdef.stats.bloom++;
3456 R_ResetViewRendering2D();
3457 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3458 R_Mesh_ColorPointer(NULL, 0, 0);
3459 R_SetupGenericShader(true);
3461 // we have a bloom image in the framebuffer
3463 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3465 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3468 r = bound(0, r_bloom_colorexponent.value / x, 1);
3469 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3470 GL_Color(r, r, r, 1);
3471 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3472 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3473 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3474 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3476 // copy the vertically blurred bloom view to a texture
3477 GL_ActiveTexture(0);
3479 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
3480 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3483 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3484 brighten = r_bloom_brighten.value;
3486 brighten *= r_hdr_range.value;
3487 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3488 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3490 for (dir = 0;dir < 2;dir++)
3492 // blend on at multiple vertical offsets to achieve a vertical blur
3493 // TODO: do offset blends using GLSL
3494 GL_BlendFunc(GL_ONE, GL_ZERO);
3495 for (x = -range;x <= range;x++)
3497 if (!dir){xoffset = 0;yoffset = x;}
3498 else {xoffset = x;yoffset = 0;}
3499 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3500 yoffset /= (float)r_bloomstate.bloomtextureheight;
3501 // compute a texcoord array with the specified x and y offset
3502 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3503 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3504 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3505 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3506 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3507 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3508 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3509 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3510 // this r value looks like a 'dot' particle, fading sharply to
3511 // black at the edges
3512 // (probably not realistic but looks good enough)
3513 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3514 //r = (dir ? 1.0f : brighten)/(range*2+1);
3515 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3516 GL_Color(r, r, r, 1);
3517 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3518 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3519 GL_BlendFunc(GL_ONE, GL_ONE);
3522 // copy the vertically blurred bloom view to a texture
3523 GL_ActiveTexture(0);
3525 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
3526 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3529 // apply subtract last
3530 // (just like it would be in a GLSL shader)
3531 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3533 GL_BlendFunc(GL_ONE, GL_ZERO);
3534 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3535 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3536 GL_Color(1, 1, 1, 1);
3537 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3538 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3540 GL_BlendFunc(GL_ONE, GL_ONE);
3541 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3542 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3543 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3544 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3545 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3546 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3547 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3549 // copy the darkened bloom view to a texture
3550 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3551 GL_ActiveTexture(0);
3553 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
3554 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3558 void R_HDR_RenderBloomTexture(void)
3560 int oldwidth, oldheight;
3561 float oldcolorscale;
3563 oldcolorscale = r_refdef.view.colorscale;
3564 oldwidth = r_refdef.view.width;
3565 oldheight = r_refdef.view.height;
3566 r_refdef.view.width = r_bloomstate.bloomwidth;
3567 r_refdef.view.height = r_bloomstate.bloomheight;
3569 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3570 // TODO: add exposure compensation features
3571 // TODO: add fp16 framebuffer support
3573 r_refdef.view.showdebug = false;
3574 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3576 R_ResetViewRendering3D();
3578 R_ClearScreen(r_refdef.fogenabled);
3579 if (r_timereport_active)
3580 R_TimeReport("HDRclear");
3583 if (r_timereport_active)
3584 R_TimeReport("visibility");
3586 r_waterstate.numwaterplanes = 0;
3587 if (r_waterstate.enabled)
3588 R_RenderWaterPlanes();
3590 r_refdef.view.showdebug = true;
3592 r_waterstate.numwaterplanes = 0;
3594 R_ResetViewRendering2D();
3596 R_Bloom_CopyHDRTexture();
3597 R_Bloom_MakeTexture();
3599 // restore the view settings
3600 r_refdef.view.width = oldwidth;
3601 r_refdef.view.height = oldheight;
3602 r_refdef.view.colorscale = oldcolorscale;
3604 R_ResetViewRendering3D();
3606 R_ClearScreen(r_refdef.fogenabled);
3607 if (r_timereport_active)
3608 R_TimeReport("viewclear");
3611 static void R_BlendView(void)
3613 if (r_bloomstate.texture_screen)
3615 // make sure the buffer is available
3616 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3618 R_ResetViewRendering2D();
3619 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3620 R_Mesh_ColorPointer(NULL, 0, 0);
3621 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3622 GL_ActiveTexture(0);CHECKGLERROR
3624 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3626 // declare alpha variable
3629 static float avgspeed;
3631 speed = VectorLength(cl.movement_velocity);
3633 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3634 avgspeed = avgspeed * (1 - a) + speed * a;
3636 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3637 speed = bound(0, speed, 1);
3638 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3640 // calculate values into a standard alpha
3643 (r_motionblur.value * speed / 80)
3645 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3648 max(0.0001, cl.time - cl.oldtime) // fps independent
3651 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3652 a = bound(0, a, r_motionblur_maxblur.value);
3654 // developer debug of current value
3655 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3660 R_SetupGenericShader(true);
3661 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3662 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3663 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3664 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3665 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3666 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3670 // copy view into the screen texture
3671 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
3672 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3675 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3677 unsigned int permutation =
3678 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3679 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3680 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3681 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3682 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3684 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3686 // render simple bloom effect
3687 // copy the screen and shrink it and darken it for the bloom process
3688 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3689 // make the bloom texture
3690 R_Bloom_MakeTexture();
3693 R_ResetViewRendering2D();
3694 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3695 R_Mesh_ColorPointer(NULL, 0, 0);
3696 GL_Color(1, 1, 1, 1);
3697 GL_BlendFunc(GL_ONE, GL_ZERO);
3698 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3699 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3700 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3701 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3702 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3703 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3704 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3705 if (r_glsl_permutation->loc_TintColor >= 0)
3706 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3707 if (r_glsl_permutation->loc_ClientTime >= 0)
3708 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3709 if (r_glsl_permutation->loc_PixelSize >= 0)
3710 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3711 if (r_glsl_permutation->loc_UserVec1 >= 0)
3713 float a=0, b=0, c=0, d=0;
3714 #if _MSC_VER >= 1400
3715 #define sscanf sscanf_s
3717 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3718 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3720 if (r_glsl_permutation->loc_UserVec2 >= 0)
3722 float a=0, b=0, c=0, d=0;
3723 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3724 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3726 if (r_glsl_permutation->loc_UserVec3 >= 0)
3728 float a=0, b=0, c=0, d=0;
3729 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3730 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3732 if (r_glsl_permutation->loc_UserVec4 >= 0)
3734 float a=0, b=0, c=0, d=0;
3735 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3736 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3738 if (r_glsl_permutation->loc_Saturation >= 0)
3739 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3740 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3741 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3747 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3749 // render high dynamic range bloom effect
3750 // the bloom texture was made earlier this render, so we just need to
3751 // blend it onto the screen...
3752 R_ResetViewRendering2D();
3753 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3754 R_Mesh_ColorPointer(NULL, 0, 0);
3755 R_SetupGenericShader(true);
3756 GL_Color(1, 1, 1, 1);
3757 GL_BlendFunc(GL_ONE, GL_ONE);
3758 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3759 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3760 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3761 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3763 else if (r_bloomstate.texture_bloom)
3765 // render simple bloom effect
3766 // copy the screen and shrink it and darken it for the bloom process
3767 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3768 // make the bloom texture
3769 R_Bloom_MakeTexture();
3770 // put the original screen image back in place and blend the bloom
3772 R_ResetViewRendering2D();
3773 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3774 R_Mesh_ColorPointer(NULL, 0, 0);
3775 GL_Color(1, 1, 1, 1);
3776 GL_BlendFunc(GL_ONE, GL_ZERO);
3777 // do both in one pass if possible
3778 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3779 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3780 if (r_textureunits.integer >= 2 && gl_combine.integer)
3782 R_SetupGenericTwoTextureShader(GL_ADD);
3783 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3784 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3788 R_SetupGenericShader(true);
3789 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3790 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3791 // now blend on the bloom texture
3792 GL_BlendFunc(GL_ONE, GL_ONE);
3793 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3794 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3796 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3797 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3799 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3801 // apply a color tint to the whole view
3802 R_ResetViewRendering2D();
3803 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3804 R_Mesh_ColorPointer(NULL, 0, 0);
3805 R_SetupGenericShader(false);
3806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3807 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3808 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3812 matrix4x4_t r_waterscrollmatrix;
3814 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3816 if (r_refdef.fog_density)
3818 r_refdef.fogcolor[0] = r_refdef.fog_red;
3819 r_refdef.fogcolor[1] = r_refdef.fog_green;
3820 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3824 VectorCopy(r_refdef.fogcolor, fogvec);
3825 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3827 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3828 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3829 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3830 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3832 // color.rgb *= ContrastBoost * SceneBrightness;
3833 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3834 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3835 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3836 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3841 void R_UpdateVariables(void)
3845 r_refdef.scene.ambient = r_ambient.value;
3847 r_refdef.farclip = 4096;
3848 if (r_refdef.scene.worldmodel)
3849 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3850 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3852 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3853 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3854 r_refdef.polygonfactor = 0;
3855 r_refdef.polygonoffset = 0;
3856 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3857 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3859 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3860 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3861 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3862 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3863 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3864 if (r_showsurfaces.integer)
3866 r_refdef.scene.rtworld = false;
3867 r_refdef.scene.rtworldshadows = false;
3868 r_refdef.scene.rtdlight = false;
3869 r_refdef.scene.rtdlightshadows = false;
3870 r_refdef.lightmapintensity = 0;
3873 if (gamemode == GAME_NEHAHRA)
3875 if (gl_fogenable.integer)
3877 r_refdef.oldgl_fogenable = true;
3878 r_refdef.fog_density = gl_fogdensity.value;
3879 r_refdef.fog_red = gl_fogred.value;
3880 r_refdef.fog_green = gl_foggreen.value;
3881 r_refdef.fog_blue = gl_fogblue.value;
3882 r_refdef.fog_alpha = 1;
3883 r_refdef.fog_start = 0;
3884 r_refdef.fog_end = gl_skyclip.value;
3886 else if (r_refdef.oldgl_fogenable)
3888 r_refdef.oldgl_fogenable = false;
3889 r_refdef.fog_density = 0;
3890 r_refdef.fog_red = 0;
3891 r_refdef.fog_green = 0;
3892 r_refdef.fog_blue = 0;
3893 r_refdef.fog_alpha = 0;
3894 r_refdef.fog_start = 0;
3895 r_refdef.fog_end = 0;
3899 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3900 r_refdef.fog_start = max(0, r_refdef.fog_start);
3901 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3903 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3905 if (r_refdef.fog_density && r_drawfog.integer)
3907 r_refdef.fogenabled = true;
3908 // this is the point where the fog reaches 0.9986 alpha, which we
3909 // consider a good enough cutoff point for the texture
3910 // (0.9986 * 256 == 255.6)
3911 if (r_fog_exp2.integer)
3912 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3914 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3915 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3916 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3917 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3918 // fog color was already set
3919 // update the fog texture
3920 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)
3921 R_BuildFogTexture();
3924 r_refdef.fogenabled = false;
3926 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3928 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3930 // build GLSL gamma texture
3931 #define RAMPWIDTH 256
3932 unsigned short ramp[RAMPWIDTH * 3];
3933 unsigned char rampbgr[RAMPWIDTH][4];
3936 r_texture_gammaramps_serial = vid_gammatables_serial;
3938 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3939 for(i = 0; i < RAMPWIDTH; ++i)
3941 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3942 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3943 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3946 if (r_texture_gammaramps)
3948 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3952 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3958 // remove GLSL gamma texture
3962 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3963 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3969 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3970 if( scenetype != r_currentscenetype ) {
3971 // store the old scenetype
3972 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3973 r_currentscenetype = scenetype;
3974 // move in the new scene
3975 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3984 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3986 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3987 if( scenetype == r_currentscenetype ) {
3988 return &r_refdef.scene;
3990 return &r_scenes_store[ scenetype ];
3999 void R_RenderView(void)
4001 r_frame++; // used only by R_GetCurrentTexture
4002 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4004 if (r_refdef.view.isoverlay)
4006 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4007 GL_Clear( GL_DEPTH_BUFFER_BIT );
4008 R_TimeReport("depthclear");
4010 r_refdef.view.showdebug = false;
4012 r_waterstate.enabled = false;
4013 r_waterstate.numwaterplanes = 0;
4021 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4022 return; //Host_Error ("R_RenderView: NULL worldmodel");
4024 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4026 // break apart the view matrix into vectors for various purposes
4027 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4028 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4029 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4030 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4031 // make an inverted copy of the view matrix for tracking sprites
4032 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4034 R_Shadow_UpdateWorldLightSelection();
4036 R_Bloom_StartFrame();
4037 R_Water_StartFrame();
4040 if (r_timereport_active)
4041 R_TimeReport("viewsetup");
4043 R_ResetViewRendering3D();
4045 if (r_refdef.view.clear || r_refdef.fogenabled)
4047 R_ClearScreen(r_refdef.fogenabled);
4048 if (r_timereport_active)
4049 R_TimeReport("viewclear");
4051 r_refdef.view.clear = true;
4053 // this produces a bloom texture to be used in R_BlendView() later
4055 R_HDR_RenderBloomTexture();
4057 r_refdef.view.showdebug = true;
4060 if (r_timereport_active)
4061 R_TimeReport("visibility");
4063 r_waterstate.numwaterplanes = 0;
4064 if (r_waterstate.enabled)
4065 R_RenderWaterPlanes();
4068 r_waterstate.numwaterplanes = 0;
4071 if (r_timereport_active)
4072 R_TimeReport("blendview");
4074 GL_Scissor(0, 0, vid.width, vid.height);
4075 GL_ScissorTest(false);
4079 void R_RenderWaterPlanes(void)
4081 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4083 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4084 if (r_timereport_active)
4085 R_TimeReport("waterworld");
4088 // don't let sound skip if going slow
4089 if (r_refdef.scene.extraupdate)
4092 R_DrawModelsAddWaterPlanes();
4093 if (r_timereport_active)
4094 R_TimeReport("watermodels");
4096 if (r_waterstate.numwaterplanes)
4098 R_Water_ProcessPlanes();
4099 if (r_timereport_active)
4100 R_TimeReport("waterscenes");
4104 extern void R_DrawLightningBeams (void);
4105 extern void VM_CL_AddPolygonsToMeshQueue (void);
4106 extern void R_DrawPortals (void);
4107 extern cvar_t cl_locs_show;
4108 static void R_DrawLocs(void);
4109 static void R_DrawEntityBBoxes(void);
4110 void R_RenderScene(void)
4112 r_refdef.stats.renders++;
4116 // don't let sound skip if going slow
4117 if (r_refdef.scene.extraupdate)
4120 R_MeshQueue_BeginScene();
4124 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);
4126 if (cl.csqc_vidvars.drawworld)
4128 // don't let sound skip if going slow
4129 if (r_refdef.scene.extraupdate)
4132 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4134 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4135 if (r_timereport_active)
4136 R_TimeReport("worldsky");
4139 if (R_DrawBrushModelsSky() && r_timereport_active)
4140 R_TimeReport("bmodelsky");
4143 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4145 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4146 if (r_timereport_active)
4147 R_TimeReport("worlddepth");
4149 if (r_depthfirst.integer >= 2)
4151 R_DrawModelsDepth();
4152 if (r_timereport_active)
4153 R_TimeReport("modeldepth");
4156 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4158 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4159 if (r_timereport_active)
4160 R_TimeReport("world");
4163 // don't let sound skip if going slow
4164 if (r_refdef.scene.extraupdate)
4168 if (r_timereport_active)
4169 R_TimeReport("models");
4171 // don't let sound skip if going slow
4172 if (r_refdef.scene.extraupdate)
4175 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4177 R_DrawModelShadows();
4179 R_ResetViewRendering3D();
4181 // don't let sound skip if going slow
4182 if (r_refdef.scene.extraupdate)
4186 R_ShadowVolumeLighting(false);
4187 if (r_timereport_active)
4188 R_TimeReport("rtlights");
4190 // don't let sound skip if going slow
4191 if (r_refdef.scene.extraupdate)
4194 if (cl.csqc_vidvars.drawworld)
4196 R_DrawLightningBeams();
4197 if (r_timereport_active)
4198 R_TimeReport("lightning");
4201 if (r_timereport_active)
4202 R_TimeReport("decals");
4205 if (r_timereport_active)
4206 R_TimeReport("particles");
4209 if (r_timereport_active)
4210 R_TimeReport("explosions");
4213 R_SetupGenericShader(true);
4214 VM_CL_AddPolygonsToMeshQueue();
4216 if (r_refdef.view.showdebug)
4218 if (cl_locs_show.integer)
4221 if (r_timereport_active)
4222 R_TimeReport("showlocs");
4225 if (r_drawportals.integer)
4228 if (r_timereport_active)
4229 R_TimeReport("portals");
4232 if (r_showbboxes.value > 0)
4234 R_DrawEntityBBoxes();
4235 if (r_timereport_active)
4236 R_TimeReport("bboxes");
4240 R_SetupGenericShader(true);
4241 R_MeshQueue_RenderTransparent();
4242 if (r_timereport_active)
4243 R_TimeReport("drawtrans");
4245 R_SetupGenericShader(true);
4247 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))
4249 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4250 if (r_timereport_active)
4251 R_TimeReport("worlddebug");
4252 R_DrawModelsDebug();
4253 if (r_timereport_active)
4254 R_TimeReport("modeldebug");
4257 R_SetupGenericShader(true);
4259 if (cl.csqc_vidvars.drawworld)
4262 if (r_timereport_active)
4263 R_TimeReport("coronas");
4266 // don't let sound skip if going slow
4267 if (r_refdef.scene.extraupdate)
4270 R_ResetViewRendering2D();
4273 static const unsigned short bboxelements[36] =
4283 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4286 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4287 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4288 GL_DepthMask(false);
4289 GL_DepthRange(0, 1);
4290 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4291 R_Mesh_Matrix(&identitymatrix);
4292 R_Mesh_ResetTextureState();
4294 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4295 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4296 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4297 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4298 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4299 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4300 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4301 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4302 R_FillColors(color4f, 8, cr, cg, cb, ca);
4303 if (r_refdef.fogenabled)
4305 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4307 f1 = FogPoint_World(v);
4309 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4310 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4311 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4314 R_Mesh_VertexPointer(vertex3f, 0, 0);
4315 R_Mesh_ColorPointer(color4f, 0, 0);
4316 R_Mesh_ResetTextureState();
4317 R_SetupGenericShader(false);
4318 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4321 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4325 prvm_edict_t *edict;
4326 prvm_prog_t *prog_save = prog;
4328 // this function draws bounding boxes of server entities
4332 GL_CullFace(GL_NONE);
4333 R_SetupGenericShader(false);
4337 for (i = 0;i < numsurfaces;i++)
4339 edict = PRVM_EDICT_NUM(surfacelist[i]);
4340 switch ((int)edict->fields.server->solid)
4342 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4343 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4344 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4345 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4346 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4347 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4349 color[3] *= r_showbboxes.value;
4350 color[3] = bound(0, color[3], 1);
4351 GL_DepthTest(!r_showdisabledepthtest.integer);
4352 GL_CullFace(r_refdef.view.cullface_front);
4353 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4359 static void R_DrawEntityBBoxes(void)
4362 prvm_edict_t *edict;
4364 prvm_prog_t *prog_save = prog;
4366 // this function draws bounding boxes of server entities
4372 for (i = 0;i < prog->num_edicts;i++)
4374 edict = PRVM_EDICT_NUM(i);
4375 if (edict->priv.server->free)
4377 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4378 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4380 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4382 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4383 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4389 unsigned short nomodelelements[24] =
4401 float nomodelvertex3f[6*3] =
4411 float nomodelcolor4f[6*4] =
4413 0.0f, 0.0f, 0.5f, 1.0f,
4414 0.0f, 0.0f, 0.5f, 1.0f,
4415 0.0f, 0.5f, 0.0f, 1.0f,
4416 0.0f, 0.5f, 0.0f, 1.0f,
4417 0.5f, 0.0f, 0.0f, 1.0f,
4418 0.5f, 0.0f, 0.0f, 1.0f
4421 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4426 // this is only called once per entity so numsurfaces is always 1, and
4427 // surfacelist is always {0}, so this code does not handle batches
4428 R_Mesh_Matrix(&ent->matrix);
4430 if (ent->flags & EF_ADDITIVE)
4432 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4433 GL_DepthMask(false);
4435 else if (ent->alpha < 1)
4437 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4438 GL_DepthMask(false);
4442 GL_BlendFunc(GL_ONE, GL_ZERO);
4445 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4446 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4447 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4448 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4449 R_SetupGenericShader(false);
4450 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4451 if (r_refdef.fogenabled)
4454 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4455 R_Mesh_ColorPointer(color4f, 0, 0);
4456 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4457 f1 = FogPoint_World(org);
4459 for (i = 0, c = color4f;i < 6;i++, c += 4)
4461 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4462 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4463 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4467 else if (ent->alpha != 1)
4469 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4470 R_Mesh_ColorPointer(color4f, 0, 0);
4471 for (i = 0, c = color4f;i < 6;i++, c += 4)
4475 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4476 R_Mesh_ResetTextureState();
4477 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4480 void R_DrawNoModel(entity_render_t *ent)
4483 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4484 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4485 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4487 // R_DrawNoModelCallback(ent, 0);
4490 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4492 vec3_t right1, right2, diff, normal;
4494 VectorSubtract (org2, org1, normal);
4496 // calculate 'right' vector for start
4497 VectorSubtract (r_refdef.view.origin, org1, diff);
4498 CrossProduct (normal, diff, right1);
4499 VectorNormalize (right1);
4501 // calculate 'right' vector for end
4502 VectorSubtract (r_refdef.view.origin, org2, diff);
4503 CrossProduct (normal, diff, right2);
4504 VectorNormalize (right2);
4506 vert[ 0] = org1[0] + width * right1[0];
4507 vert[ 1] = org1[1] + width * right1[1];
4508 vert[ 2] = org1[2] + width * right1[2];
4509 vert[ 3] = org1[0] - width * right1[0];
4510 vert[ 4] = org1[1] - width * right1[1];
4511 vert[ 5] = org1[2] - width * right1[2];
4512 vert[ 6] = org2[0] - width * right2[0];
4513 vert[ 7] = org2[1] - width * right2[1];
4514 vert[ 8] = org2[2] - width * right2[2];
4515 vert[ 9] = org2[0] + width * right2[0];
4516 vert[10] = org2[1] + width * right2[1];
4517 vert[11] = org2[2] + width * right2[2];
4520 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4522 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)
4524 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4528 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4529 fog = FogPoint_World(origin);
4531 R_Mesh_Matrix(&identitymatrix);
4532 GL_BlendFunc(blendfunc1, blendfunc2);
4534 GL_CullFace(GL_NONE);
4536 GL_DepthMask(false);
4537 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4538 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4539 GL_DepthTest(!depthdisable);
4541 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4542 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4543 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4544 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4545 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4546 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4547 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4548 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4549 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4550 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4551 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4552 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4554 R_Mesh_VertexPointer(vertex3f, 0, 0);
4555 R_Mesh_ColorPointer(NULL, 0, 0);
4556 R_Mesh_ResetTextureState();
4557 R_SetupGenericShader(true);
4558 R_Mesh_TexBind(0, R_GetTexture(texture));
4559 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4560 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4561 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4562 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4564 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4566 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4567 GL_BlendFunc(blendfunc1, GL_ONE);
4569 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4570 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4574 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4579 VectorSet(v, x, y, z);
4580 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4581 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4583 if (i == mesh->numvertices)
4585 if (mesh->numvertices < mesh->maxvertices)
4587 VectorCopy(v, vertex3f);
4588 mesh->numvertices++;
4590 return mesh->numvertices;
4596 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4600 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4601 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4602 e = mesh->element3i + mesh->numtriangles * 3;
4603 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4605 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4606 if (mesh->numtriangles < mesh->maxtriangles)
4611 mesh->numtriangles++;
4613 element[1] = element[2];
4617 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4621 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4622 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4623 e = mesh->element3i + mesh->numtriangles * 3;
4624 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4626 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4627 if (mesh->numtriangles < mesh->maxtriangles)
4632 mesh->numtriangles++;
4634 element[1] = element[2];
4638 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4639 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4641 int planenum, planenum2;
4644 mplane_t *plane, *plane2;
4646 double temppoints[2][256*3];
4647 // figure out how large a bounding box we need to properly compute this brush
4649 for (w = 0;w < numplanes;w++)
4650 maxdist = max(maxdist, planes[w].dist);
4651 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4652 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4653 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4657 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4658 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4660 if (planenum2 == planenum)
4662 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);
4665 if (tempnumpoints < 3)
4667 // generate elements forming a triangle fan for this polygon
4668 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4672 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)
4674 texturelayer_t *layer;
4675 layer = t->currentlayers + t->currentnumlayers++;
4677 layer->depthmask = depthmask;
4678 layer->blendfunc1 = blendfunc1;
4679 layer->blendfunc2 = blendfunc2;
4680 layer->texture = texture;
4681 layer->texmatrix = *matrix;
4682 layer->color[0] = r * r_refdef.view.colorscale;
4683 layer->color[1] = g * r_refdef.view.colorscale;
4684 layer->color[2] = b * r_refdef.view.colorscale;
4685 layer->color[3] = a;
4688 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4691 index = parms[2] + r_refdef.scene.time * parms[3];
4692 index -= floor(index);
4696 case Q3WAVEFUNC_NONE:
4697 case Q3WAVEFUNC_NOISE:
4698 case Q3WAVEFUNC_COUNT:
4701 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4702 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4703 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4704 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4705 case Q3WAVEFUNC_TRIANGLE:
4707 f = index - floor(index);
4718 return (float)(parms[0] + parms[1] * f);
4721 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4726 matrix4x4_t matrix, temp;
4727 switch(tcmod->tcmod)
4731 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4732 matrix = r_waterscrollmatrix;
4734 matrix = identitymatrix;
4736 case Q3TCMOD_ENTITYTRANSLATE:
4737 // this is used in Q3 to allow the gamecode to control texcoord
4738 // scrolling on the entity, which is not supported in darkplaces yet.
4739 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4741 case Q3TCMOD_ROTATE:
4742 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4743 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4744 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4747 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4749 case Q3TCMOD_SCROLL:
4750 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4752 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4753 w = (int) tcmod->parms[0];
4754 h = (int) tcmod->parms[1];
4755 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4757 idx = (int) floor(f * w * h);
4758 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4760 case Q3TCMOD_STRETCH:
4761 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4762 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4764 case Q3TCMOD_TRANSFORM:
4765 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4766 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4767 VectorSet(tcmat + 6, 0 , 0 , 1);
4768 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4769 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4771 case Q3TCMOD_TURBULENT:
4772 // this is handled in the RSurf_PrepareVertices function
4773 matrix = identitymatrix;
4777 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4780 texture_t *R_GetCurrentTexture(texture_t *t)
4783 const entity_render_t *ent = rsurface.entity;
4784 dp_model_t *model = ent->model;
4785 q3shaderinfo_layer_tcmod_t *tcmod;
4787 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4788 return t->currentframe;
4789 t->update_lastrenderframe = r_frame;
4790 t->update_lastrenderentity = (void *)ent;
4792 // switch to an alternate material if this is a q1bsp animated material
4794 texture_t *texture = t;
4795 int s = ent->skinnum;
4796 if ((unsigned int)s >= (unsigned int)model->numskins)
4798 if (model->skinscenes)
4800 if (model->skinscenes[s].framecount > 1)
4801 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4803 s = model->skinscenes[s].firstframe;
4806 t = t + s * model->num_surfaces;
4809 // use an alternate animation if the entity's frame is not 0,
4810 // and only if the texture has an alternate animation
4811 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4812 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4814 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4816 texture->currentframe = t;
4819 // update currentskinframe to be a qw skin or animation frame
4820 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
4822 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4824 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4825 if (developer_loading.integer)
4826 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4827 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);
4829 t->currentskinframe = r_qwskincache_skinframe[i];
4830 if (t->currentskinframe == NULL)
4831 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4833 else if (t->numskinframes >= 2)
4834 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4835 if (t->backgroundnumskinframes >= 2)
4836 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4838 t->currentmaterialflags = t->basematerialflags;
4839 t->currentalpha = ent->alpha;
4840 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4841 t->currentalpha *= r_wateralpha.value;
4842 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4843 t->currentalpha *= t->r_water_wateralpha;
4844 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4845 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4846 if (!(ent->flags & RENDER_LIGHT))
4847 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4848 else if (rsurface.modeltexcoordlightmap2f == NULL)
4850 // pick a model lighting mode
4851 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4852 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4854 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4856 if (ent->effects & EF_ADDITIVE)
4857 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4858 else if (t->currentalpha < 1)
4859 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4860 if (ent->effects & EF_DOUBLESIDED)
4861 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4862 if (ent->effects & EF_NODEPTHTEST)
4863 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4864 if (ent->flags & RENDER_VIEWMODEL)
4865 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4866 if (t->backgroundnumskinframes)
4867 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4868 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4870 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4871 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4874 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4876 // there is no tcmod
4877 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4879 t->currenttexmatrix = r_waterscrollmatrix;
4880 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
4884 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
4885 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
4888 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4889 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
4890 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4891 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
4893 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4894 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4895 t->glosstexture = r_texture_black;
4896 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4897 t->backgroundglosstexture = r_texture_black;
4898 t->specularpower = r_shadow_glossexponent.value;
4899 // TODO: store reference values for these in the texture?
4900 t->specularscale = 0;
4901 if (r_shadow_gloss.integer > 0)
4903 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4905 if (r_shadow_glossintensity.value > 0)
4907 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4908 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4909 t->specularscale = r_shadow_glossintensity.value;
4912 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4914 t->glosstexture = r_texture_white;
4915 t->backgroundglosstexture = r_texture_white;
4916 t->specularscale = r_shadow_gloss2intensity.value;
4920 // lightmaps mode looks bad with dlights using actual texturing, so turn
4921 // off the colormap and glossmap, but leave the normalmap on as it still
4922 // accurately represents the shading involved
4923 if (gl_lightmaps.integer)
4925 t->basetexture = r_texture_grey128;
4926 t->backgroundbasetexture = NULL;
4927 t->specularscale = 0;
4928 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4931 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4932 VectorClear(t->dlightcolor);
4933 t->currentnumlayers = 0;
4934 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4937 int blendfunc1, blendfunc2, depthmask;
4938 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4940 blendfunc1 = GL_SRC_ALPHA;
4941 blendfunc2 = GL_ONE;
4943 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4945 blendfunc1 = GL_SRC_ALPHA;
4946 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4948 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4950 blendfunc1 = t->customblendfunc[0];
4951 blendfunc2 = t->customblendfunc[1];
4955 blendfunc1 = GL_ONE;
4956 blendfunc2 = GL_ZERO;
4958 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4959 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4960 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4961 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4963 // fullbright is not affected by r_refdef.lightmapintensity
4964 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]);
4965 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4966 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]);
4967 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4968 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]);
4972 vec3_t ambientcolor;
4974 // set the color tint used for lights affecting this surface
4975 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4977 // q3bsp has no lightmap updates, so the lightstylevalue that
4978 // would normally be baked into the lightmap must be
4979 // applied to the color
4980 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4981 if (ent->model->type == mod_brushq3)
4982 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4983 colorscale *= r_refdef.lightmapintensity;
4984 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4985 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4986 // basic lit geometry
4987 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]);
4988 // add pants/shirt if needed
4989 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4990 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]);
4991 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4992 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]);
4993 // now add ambient passes if needed
4994 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4996 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]);
4997 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4998 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]);
4999 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5000 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]);
5003 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5004 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]);
5005 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5007 // if this is opaque use alpha blend which will darken the earlier
5010 // if this is an alpha blended material, all the earlier passes
5011 // were darkened by fog already, so we only need to add the fog
5012 // color ontop through the fog mask texture
5014 // if this is an additive blended material, all the earlier passes
5015 // were darkened by fog already, and we should not add fog color
5016 // (because the background was not darkened, there is no fog color
5017 // that was lost behind it).
5018 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]);
5022 return t->currentframe;
5025 rsurfacestate_t rsurface;
5027 void R_Mesh_ResizeArrays(int newvertices)
5030 if (rsurface.array_size >= newvertices)
5032 if (rsurface.array_modelvertex3f)
5033 Mem_Free(rsurface.array_modelvertex3f);
5034 rsurface.array_size = (newvertices + 1023) & ~1023;
5035 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5036 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5037 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5038 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5039 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5040 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5041 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5042 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5043 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5044 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5045 rsurface.array_color4f = base + rsurface.array_size * 27;
5046 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5049 void RSurf_ActiveWorldEntity(void)
5051 dp_model_t *model = r_refdef.scene.worldmodel;
5052 //if (rsurface.entity == r_refdef.scene.worldentity)
5054 rsurface.entity = r_refdef.scene.worldentity;
5055 if (rsurface.array_size < model->surfmesh.num_vertices)
5056 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5057 rsurface.matrix = identitymatrix;
5058 rsurface.inversematrix = identitymatrix;
5059 R_Mesh_Matrix(&identitymatrix);
5060 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5061 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5062 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5063 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5064 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5065 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5066 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5067 rsurface.frameblend[0].lerp = 1;
5068 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5069 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5070 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5071 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5072 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5073 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5074 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5075 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5076 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5077 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5078 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5079 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5080 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5081 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5082 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5083 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5084 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5085 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5086 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5087 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5088 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5089 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5090 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5091 rsurface.modelelement3i = model->surfmesh.data_element3i;
5092 rsurface.modelelement3s = model->surfmesh.data_element3s;
5093 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5094 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5095 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5096 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5097 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5098 rsurface.modelsurfaces = model->data_surfaces;
5099 rsurface.generatedvertex = false;
5100 rsurface.vertex3f = rsurface.modelvertex3f;
5101 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5102 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5103 rsurface.svector3f = rsurface.modelsvector3f;
5104 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5105 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5106 rsurface.tvector3f = rsurface.modeltvector3f;
5107 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5108 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5109 rsurface.normal3f = rsurface.modelnormal3f;
5110 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5111 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5112 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5115 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5117 dp_model_t *model = ent->model;
5118 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5120 rsurface.entity = (entity_render_t *)ent;
5121 if (rsurface.array_size < model->surfmesh.num_vertices)
5122 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5123 rsurface.matrix = ent->matrix;
5124 rsurface.inversematrix = ent->inversematrix;
5125 R_Mesh_Matrix(&rsurface.matrix);
5126 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5127 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5128 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5129 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5130 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5131 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5132 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5133 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5134 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5135 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5136 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5137 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5138 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5139 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5140 if (ent->model->brush.submodel)
5142 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5143 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5145 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5149 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5150 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5151 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5152 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5153 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5155 else if (wantnormals)
5157 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5158 rsurface.modelsvector3f = NULL;
5159 rsurface.modeltvector3f = NULL;
5160 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5161 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5165 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5166 rsurface.modelsvector3f = NULL;
5167 rsurface.modeltvector3f = NULL;
5168 rsurface.modelnormal3f = NULL;
5169 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5171 rsurface.modelvertex3f_bufferobject = 0;
5172 rsurface.modelvertex3f_bufferoffset = 0;
5173 rsurface.modelsvector3f_bufferobject = 0;
5174 rsurface.modelsvector3f_bufferoffset = 0;
5175 rsurface.modeltvector3f_bufferobject = 0;
5176 rsurface.modeltvector3f_bufferoffset = 0;
5177 rsurface.modelnormal3f_bufferobject = 0;
5178 rsurface.modelnormal3f_bufferoffset = 0;
5179 rsurface.generatedvertex = true;
5183 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5184 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5185 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5186 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5187 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5188 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5189 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5190 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5191 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5192 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5193 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5194 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5195 rsurface.generatedvertex = false;
5197 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5198 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5199 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5200 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5201 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5202 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5203 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5204 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5205 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5206 rsurface.modelelement3i = model->surfmesh.data_element3i;
5207 rsurface.modelelement3s = model->surfmesh.data_element3s;
5208 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5209 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5210 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5211 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5212 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5213 rsurface.modelsurfaces = model->data_surfaces;
5214 rsurface.vertex3f = rsurface.modelvertex3f;
5215 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5216 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5217 rsurface.svector3f = rsurface.modelsvector3f;
5218 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5219 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5220 rsurface.tvector3f = rsurface.modeltvector3f;
5221 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5222 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5223 rsurface.normal3f = rsurface.modelnormal3f;
5224 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5225 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5226 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5229 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5230 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5233 int texturesurfaceindex;
5238 const float *v1, *in_tc;
5240 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5242 q3shaderinfo_deform_t *deform;
5243 // 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
5244 if (rsurface.generatedvertex)
5246 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5247 generatenormals = true;
5248 for (i = 0;i < Q3MAXDEFORMS;i++)
5250 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5252 generatetangents = true;
5253 generatenormals = true;
5255 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5256 generatenormals = true;
5258 if (generatenormals && !rsurface.modelnormal3f)
5260 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5261 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5262 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5263 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5265 if (generatetangents && !rsurface.modelsvector3f)
5267 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5268 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5269 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5270 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5271 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5272 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5273 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);
5276 rsurface.vertex3f = rsurface.modelvertex3f;
5277 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5278 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5279 rsurface.svector3f = rsurface.modelsvector3f;
5280 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5281 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5282 rsurface.tvector3f = rsurface.modeltvector3f;
5283 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5284 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5285 rsurface.normal3f = rsurface.modelnormal3f;
5286 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5287 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5288 // if vertices are deformed (sprite flares and things in maps, possibly
5289 // water waves, bulges and other deformations), generate them into
5290 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5291 // (may be static model data or generated data for an animated model, or
5292 // the previous deform pass)
5293 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5295 switch (deform->deform)
5298 case Q3DEFORM_PROJECTIONSHADOW:
5299 case Q3DEFORM_TEXT0:
5300 case Q3DEFORM_TEXT1:
5301 case Q3DEFORM_TEXT2:
5302 case Q3DEFORM_TEXT3:
5303 case Q3DEFORM_TEXT4:
5304 case Q3DEFORM_TEXT5:
5305 case Q3DEFORM_TEXT6:
5306 case Q3DEFORM_TEXT7:
5309 case Q3DEFORM_AUTOSPRITE:
5310 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5311 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5312 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5313 VectorNormalize(newforward);
5314 VectorNormalize(newright);
5315 VectorNormalize(newup);
5316 // make deformed versions of only the model vertices used by the specified surfaces
5317 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5319 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5320 // a single autosprite surface can contain multiple sprites...
5321 for (j = 0;j < surface->num_vertices - 3;j += 4)
5323 VectorClear(center);
5324 for (i = 0;i < 4;i++)
5325 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5326 VectorScale(center, 0.25f, center);
5327 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5328 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5329 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5330 for (i = 0;i < 4;i++)
5332 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5333 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5336 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);
5337 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);
5339 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5340 rsurface.vertex3f_bufferobject = 0;
5341 rsurface.vertex3f_bufferoffset = 0;
5342 rsurface.svector3f = rsurface.array_deformedsvector3f;
5343 rsurface.svector3f_bufferobject = 0;
5344 rsurface.svector3f_bufferoffset = 0;
5345 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5346 rsurface.tvector3f_bufferobject = 0;
5347 rsurface.tvector3f_bufferoffset = 0;
5348 rsurface.normal3f = rsurface.array_deformednormal3f;
5349 rsurface.normal3f_bufferobject = 0;
5350 rsurface.normal3f_bufferoffset = 0;
5352 case Q3DEFORM_AUTOSPRITE2:
5353 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5354 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5355 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5356 VectorNormalize(newforward);
5357 VectorNormalize(newright);
5358 VectorNormalize(newup);
5359 // make deformed versions of only the model vertices used by the specified surfaces
5360 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5362 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5363 const float *v1, *v2;
5373 memset(shortest, 0, sizeof(shortest));
5374 // a single autosprite surface can contain multiple sprites...
5375 for (j = 0;j < surface->num_vertices - 3;j += 4)
5377 VectorClear(center);
5378 for (i = 0;i < 4;i++)
5379 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5380 VectorScale(center, 0.25f, center);
5381 // find the two shortest edges, then use them to define the
5382 // axis vectors for rotating around the central axis
5383 for (i = 0;i < 6;i++)
5385 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5386 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5388 Debug_PolygonBegin(NULL, 0);
5389 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5390 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);
5391 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5394 l = VectorDistance2(v1, v2);
5395 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5397 l += (1.0f / 1024.0f);
5398 if (shortest[0].length2 > l || i == 0)
5400 shortest[1] = shortest[0];
5401 shortest[0].length2 = l;
5402 shortest[0].v1 = v1;
5403 shortest[0].v2 = v2;
5405 else if (shortest[1].length2 > l || i == 1)
5407 shortest[1].length2 = l;
5408 shortest[1].v1 = v1;
5409 shortest[1].v2 = v2;
5412 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5413 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5415 Debug_PolygonBegin(NULL, 0);
5416 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5417 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);
5418 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5421 // this calculates the right vector from the shortest edge
5422 // and the up vector from the edge midpoints
5423 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5424 VectorNormalize(right);
5425 VectorSubtract(end, start, up);
5426 VectorNormalize(up);
5427 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5428 VectorSubtract(rsurface.modelorg, center, forward);
5429 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5430 VectorNegate(forward, forward);
5431 VectorReflect(forward, 0, up, forward);
5432 VectorNormalize(forward);
5433 CrossProduct(up, forward, newright);
5434 VectorNormalize(newright);
5436 Debug_PolygonBegin(NULL, 0);
5437 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);
5438 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5439 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5443 Debug_PolygonBegin(NULL, 0);
5444 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5445 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5446 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5449 // rotate the quad around the up axis vector, this is made
5450 // especially easy by the fact we know the quad is flat,
5451 // so we only have to subtract the center position and
5452 // measure distance along the right vector, and then
5453 // multiply that by the newright vector and add back the
5455 // we also need to subtract the old position to undo the
5456 // displacement from the center, which we do with a
5457 // DotProduct, the subtraction/addition of center is also
5458 // optimized into DotProducts here
5459 l = DotProduct(right, center);
5460 for (i = 0;i < 4;i++)
5462 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5463 f = DotProduct(right, v1) - l;
5464 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5467 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);
5468 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);
5470 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5471 rsurface.vertex3f_bufferobject = 0;
5472 rsurface.vertex3f_bufferoffset = 0;
5473 rsurface.svector3f = rsurface.array_deformedsvector3f;
5474 rsurface.svector3f_bufferobject = 0;
5475 rsurface.svector3f_bufferoffset = 0;
5476 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5477 rsurface.tvector3f_bufferobject = 0;
5478 rsurface.tvector3f_bufferoffset = 0;
5479 rsurface.normal3f = rsurface.array_deformednormal3f;
5480 rsurface.normal3f_bufferobject = 0;
5481 rsurface.normal3f_bufferoffset = 0;
5483 case Q3DEFORM_NORMAL:
5484 // deform the normals to make reflections wavey
5485 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5487 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5488 for (j = 0;j < surface->num_vertices;j++)
5491 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5492 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5493 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5494 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5495 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5496 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5497 VectorNormalize(normal);
5499 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);
5501 rsurface.svector3f = rsurface.array_deformedsvector3f;
5502 rsurface.svector3f_bufferobject = 0;
5503 rsurface.svector3f_bufferoffset = 0;
5504 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5505 rsurface.tvector3f_bufferobject = 0;
5506 rsurface.tvector3f_bufferoffset = 0;
5507 rsurface.normal3f = rsurface.array_deformednormal3f;
5508 rsurface.normal3f_bufferobject = 0;
5509 rsurface.normal3f_bufferoffset = 0;
5512 // deform vertex array to make wavey water and flags and such
5513 waveparms[0] = deform->waveparms[0];
5514 waveparms[1] = deform->waveparms[1];
5515 waveparms[2] = deform->waveparms[2];
5516 waveparms[3] = deform->waveparms[3];
5517 // this is how a divisor of vertex influence on deformation
5518 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5519 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5520 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5522 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5523 for (j = 0;j < surface->num_vertices;j++)
5525 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5526 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5527 // if the wavefunc depends on time, evaluate it per-vertex
5530 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5531 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5533 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5536 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5537 rsurface.vertex3f_bufferobject = 0;
5538 rsurface.vertex3f_bufferoffset = 0;
5540 case Q3DEFORM_BULGE:
5541 // deform vertex array to make the surface have moving bulges
5542 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5544 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5545 for (j = 0;j < surface->num_vertices;j++)
5547 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5548 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5551 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5552 rsurface.vertex3f_bufferobject = 0;
5553 rsurface.vertex3f_bufferoffset = 0;
5556 // deform vertex array
5557 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5558 VectorScale(deform->parms, scale, waveparms);
5559 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5561 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5562 for (j = 0;j < surface->num_vertices;j++)
5563 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5565 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5566 rsurface.vertex3f_bufferobject = 0;
5567 rsurface.vertex3f_bufferoffset = 0;
5571 // generate texcoords based on the chosen texcoord source
5572 switch(rsurface.texture->tcgen.tcgen)
5575 case Q3TCGEN_TEXTURE:
5576 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5577 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5578 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5580 case Q3TCGEN_LIGHTMAP:
5581 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5582 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5583 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5585 case Q3TCGEN_VECTOR:
5586 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5588 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5589 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)
5591 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5592 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5595 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5596 rsurface.texcoordtexture2f_bufferobject = 0;
5597 rsurface.texcoordtexture2f_bufferoffset = 0;
5599 case Q3TCGEN_ENVIRONMENT:
5600 // make environment reflections using a spheremap
5601 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5603 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5604 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5605 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5606 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5607 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5609 // identical to Q3A's method, but executed in worldspace so
5610 // carried models can be shiny too
5612 float viewer[3], d, reflected[3], worldreflected[3];
5614 VectorSubtract(rsurface.modelorg, vertex, viewer);
5615 // VectorNormalize(viewer);
5617 d = DotProduct(normal, viewer);
5619 reflected[0] = normal[0]*2*d - viewer[0];
5620 reflected[1] = normal[1]*2*d - viewer[1];
5621 reflected[2] = normal[2]*2*d - viewer[2];
5622 // note: this is proportinal to viewer, so we can normalize later
5624 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5625 VectorNormalize(worldreflected);
5627 // note: this sphere map only uses world x and z!
5628 // so positive and negative y will LOOK THE SAME.
5629 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5630 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5633 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5634 rsurface.texcoordtexture2f_bufferobject = 0;
5635 rsurface.texcoordtexture2f_bufferoffset = 0;
5638 // the only tcmod that needs software vertex processing is turbulent, so
5639 // check for it here and apply the changes if needed
5640 // and we only support that as the first one
5641 // (handling a mixture of turbulent and other tcmods would be problematic
5642 // without punting it entirely to a software path)
5643 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5645 amplitude = rsurface.texture->tcmods[0].parms[1];
5646 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5647 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5649 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5650 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)
5652 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5653 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5656 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5657 rsurface.texcoordtexture2f_bufferobject = 0;
5658 rsurface.texcoordtexture2f_bufferoffset = 0;
5660 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5661 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5662 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5663 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5666 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5669 const msurface_t *surface = texturesurfacelist[0];
5670 const msurface_t *surface2;
5675 // TODO: lock all array ranges before render, rather than on each surface
5676 if (texturenumsurfaces == 1)
5678 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5679 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5681 else if (r_batchmode.integer == 2)
5683 #define MAXBATCHTRIANGLES 4096
5684 int batchtriangles = 0;
5685 int batchelements[MAXBATCHTRIANGLES*3];
5686 for (i = 0;i < texturenumsurfaces;i = j)
5688 surface = texturesurfacelist[i];
5690 if (surface->num_triangles > MAXBATCHTRIANGLES)
5692 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5695 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5696 batchtriangles = surface->num_triangles;
5697 firstvertex = surface->num_firstvertex;
5698 endvertex = surface->num_firstvertex + surface->num_vertices;
5699 for (;j < texturenumsurfaces;j++)
5701 surface2 = texturesurfacelist[j];
5702 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5704 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5705 batchtriangles += surface2->num_triangles;
5706 firstvertex = min(firstvertex, surface2->num_firstvertex);
5707 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5709 surface2 = texturesurfacelist[j-1];
5710 numvertices = endvertex - firstvertex;
5711 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5714 else if (r_batchmode.integer == 1)
5716 for (i = 0;i < texturenumsurfaces;i = j)
5718 surface = texturesurfacelist[i];
5719 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5720 if (texturesurfacelist[j] != surface2)
5722 surface2 = texturesurfacelist[j-1];
5723 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5724 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5725 GL_LockArrays(surface->num_firstvertex, numvertices);
5726 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5731 for (i = 0;i < texturenumsurfaces;i++)
5733 surface = texturesurfacelist[i];
5734 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5735 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5740 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5742 int i, planeindex, vertexindex;
5746 r_waterstate_waterplane_t *p, *bestp;
5747 msurface_t *surface;
5748 if (r_waterstate.renderingscene)
5750 for (i = 0;i < texturenumsurfaces;i++)
5752 surface = texturesurfacelist[i];
5753 if (lightmaptexunit >= 0)
5754 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5755 if (deluxemaptexunit >= 0)
5756 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5757 // pick the closest matching water plane
5760 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5763 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5765 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5766 d += fabs(PlaneDiff(vert, &p->plane));
5768 if (bestd > d || !bestp)
5776 if (refractiontexunit >= 0)
5777 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5778 if (reflectiontexunit >= 0)
5779 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5783 if (refractiontexunit >= 0)
5784 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5785 if (reflectiontexunit >= 0)
5786 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5788 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5789 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5793 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5797 const msurface_t *surface = texturesurfacelist[0];
5798 const msurface_t *surface2;
5803 // TODO: lock all array ranges before render, rather than on each surface
5804 if (texturenumsurfaces == 1)
5806 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5807 if (deluxemaptexunit >= 0)
5808 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5809 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5810 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5812 else if (r_batchmode.integer == 2)
5814 #define MAXBATCHTRIANGLES 4096
5815 int batchtriangles = 0;
5816 int batchelements[MAXBATCHTRIANGLES*3];
5817 for (i = 0;i < texturenumsurfaces;i = j)
5819 surface = texturesurfacelist[i];
5820 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5821 if (deluxemaptexunit >= 0)
5822 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5824 if (surface->num_triangles > MAXBATCHTRIANGLES)
5826 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5829 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5830 batchtriangles = surface->num_triangles;
5831 firstvertex = surface->num_firstvertex;
5832 endvertex = surface->num_firstvertex + surface->num_vertices;
5833 for (;j < texturenumsurfaces;j++)
5835 surface2 = texturesurfacelist[j];
5836 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5838 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5839 batchtriangles += surface2->num_triangles;
5840 firstvertex = min(firstvertex, surface2->num_firstvertex);
5841 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5843 surface2 = texturesurfacelist[j-1];
5844 numvertices = endvertex - firstvertex;
5845 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5848 else if (r_batchmode.integer == 1)
5851 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5852 for (i = 0;i < texturenumsurfaces;i = j)
5854 surface = texturesurfacelist[i];
5855 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5856 if (texturesurfacelist[j] != surface2)
5858 Con_Printf(" %i", j - i);
5861 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5863 for (i = 0;i < texturenumsurfaces;i = j)
5865 surface = texturesurfacelist[i];
5866 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5867 if (deluxemaptexunit >= 0)
5868 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5869 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5870 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5873 Con_Printf(" %i", j - i);
5875 surface2 = texturesurfacelist[j-1];
5876 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5877 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5878 GL_LockArrays(surface->num_firstvertex, numvertices);
5879 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5887 for (i = 0;i < texturenumsurfaces;i++)
5889 surface = texturesurfacelist[i];
5890 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5891 if (deluxemaptexunit >= 0)
5892 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5893 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5894 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5899 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5902 int texturesurfaceindex;
5903 if (r_showsurfaces.integer == 2)
5905 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5907 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5908 for (j = 0;j < surface->num_triangles;j++)
5910 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5911 GL_Color(f, f, f, 1);
5912 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5918 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5920 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5921 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5922 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);
5923 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5924 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5929 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5931 int texturesurfaceindex;
5934 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5936 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5937 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)
5945 rsurface.lightmapcolor4f = rsurface.array_color4f;
5946 rsurface.lightmapcolor4f_bufferobject = 0;
5947 rsurface.lightmapcolor4f_bufferoffset = 0;
5950 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5952 int texturesurfaceindex;
5956 if (rsurface.lightmapcolor4f)
5958 // generate color arrays for the surfaces in this list
5959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5961 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5962 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)
5964 f = FogPoint_Model(v);
5974 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5976 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5977 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)
5979 f = FogPoint_Model(v);
5987 rsurface.lightmapcolor4f = rsurface.array_color4f;
5988 rsurface.lightmapcolor4f_bufferobject = 0;
5989 rsurface.lightmapcolor4f_bufferoffset = 0;
5992 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5994 int texturesurfaceindex;
5998 if (!rsurface.lightmapcolor4f)
6000 // generate color arrays for the surfaces in this list
6001 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6003 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6004 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)
6006 f = FogPoint_Model(v);
6007 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6008 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6009 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6013 rsurface.lightmapcolor4f = rsurface.array_color4f;
6014 rsurface.lightmapcolor4f_bufferobject = 0;
6015 rsurface.lightmapcolor4f_bufferoffset = 0;
6018 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6020 int texturesurfaceindex;
6023 if (!rsurface.lightmapcolor4f)
6025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6027 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6028 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)
6036 rsurface.lightmapcolor4f = rsurface.array_color4f;
6037 rsurface.lightmapcolor4f_bufferobject = 0;
6038 rsurface.lightmapcolor4f_bufferoffset = 0;
6041 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6043 int texturesurfaceindex;
6046 if (!rsurface.lightmapcolor4f)
6048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6050 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6051 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)
6053 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6054 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6055 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6059 rsurface.lightmapcolor4f = rsurface.array_color4f;
6060 rsurface.lightmapcolor4f_bufferobject = 0;
6061 rsurface.lightmapcolor4f_bufferoffset = 0;
6064 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6067 rsurface.lightmapcolor4f = NULL;
6068 rsurface.lightmapcolor4f_bufferobject = 0;
6069 rsurface.lightmapcolor4f_bufferoffset = 0;
6070 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6071 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6072 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6073 GL_Color(r, g, b, a);
6074 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6077 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6079 // TODO: optimize applyfog && applycolor case
6080 // just apply fog if necessary, and tint the fog color array if necessary
6081 rsurface.lightmapcolor4f = NULL;
6082 rsurface.lightmapcolor4f_bufferobject = 0;
6083 rsurface.lightmapcolor4f_bufferoffset = 0;
6084 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6085 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6086 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6087 GL_Color(r, g, b, a);
6088 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6091 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6093 int texturesurfaceindex;
6097 if (texturesurfacelist[0]->lightmapinfo)
6099 // generate color arrays for the surfaces in this list
6100 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6102 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6103 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6105 if (surface->lightmapinfo->samples)
6107 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6108 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6109 VectorScale(lm, scale, c);
6110 if (surface->lightmapinfo->styles[1] != 255)
6112 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6114 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6115 VectorMA(c, scale, lm, c);
6116 if (surface->lightmapinfo->styles[2] != 255)
6119 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6120 VectorMA(c, scale, lm, c);
6121 if (surface->lightmapinfo->styles[3] != 255)
6124 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6125 VectorMA(c, scale, lm, c);
6135 rsurface.lightmapcolor4f = rsurface.array_color4f;
6136 rsurface.lightmapcolor4f_bufferobject = 0;
6137 rsurface.lightmapcolor4f_bufferoffset = 0;
6141 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6142 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6143 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6145 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6146 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6147 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6148 GL_Color(r, g, b, a);
6149 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6152 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6154 int texturesurfaceindex;
6157 float *v, *c, *c2, alpha;
6158 vec3_t ambientcolor;
6159 vec3_t diffusecolor;
6163 VectorCopy(rsurface.modellight_lightdir, lightdir);
6164 f = 0.5f * r_refdef.lightmapintensity;
6165 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6166 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6167 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6168 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6169 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6170 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6172 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6174 // generate color arrays for the surfaces in this list
6175 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6177 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6178 int numverts = surface->num_vertices;
6179 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6180 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6181 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6182 // q3-style directional shading
6183 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6185 if ((f = DotProduct(c2, lightdir)) > 0)
6186 VectorMA(ambientcolor, f, diffusecolor, c);
6188 VectorCopy(ambientcolor, c);
6196 rsurface.lightmapcolor4f = rsurface.array_color4f;
6197 rsurface.lightmapcolor4f_bufferobject = 0;
6198 rsurface.lightmapcolor4f_bufferoffset = 0;
6199 *applycolor = false;
6203 *r = ambientcolor[0];
6204 *g = ambientcolor[1];
6205 *b = ambientcolor[2];
6206 rsurface.lightmapcolor4f = NULL;
6207 rsurface.lightmapcolor4f_bufferobject = 0;
6208 rsurface.lightmapcolor4f_bufferoffset = 0;
6212 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6214 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6215 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6216 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6217 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6218 GL_Color(r, g, b, a);
6219 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6222 void RSurf_SetupDepthAndCulling(void)
6224 // submodels are biased to avoid z-fighting with world surfaces that they
6225 // may be exactly overlapping (avoids z-fighting artifacts on certain
6226 // doors and things in Quake maps)
6227 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6228 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6229 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6230 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6233 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6235 // transparent sky would be ridiculous
6236 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6238 R_SetupGenericShader(false);
6241 skyrendernow = false;
6242 // we have to force off the water clipping plane while rendering sky
6246 // restore entity matrix
6247 R_Mesh_Matrix(&rsurface.matrix);
6249 RSurf_SetupDepthAndCulling();
6251 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6252 // skymasking on them, and Quake3 never did sky masking (unlike
6253 // software Quake and software Quake2), so disable the sky masking
6254 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6255 // and skymasking also looks very bad when noclipping outside the
6256 // level, so don't use it then either.
6257 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6259 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6260 R_Mesh_ColorPointer(NULL, 0, 0);
6261 R_Mesh_ResetTextureState();
6262 if (skyrendermasked)
6264 R_SetupDepthOrShadowShader();
6265 // depth-only (masking)
6266 GL_ColorMask(0,0,0,0);
6267 // just to make sure that braindead drivers don't draw
6268 // anything despite that colormask...
6269 GL_BlendFunc(GL_ZERO, GL_ONE);
6273 R_SetupGenericShader(false);
6275 GL_BlendFunc(GL_ONE, GL_ZERO);
6277 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6278 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6279 if (skyrendermasked)
6280 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6282 R_Mesh_ResetTextureState();
6283 GL_Color(1, 1, 1, 1);
6286 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6288 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6291 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6292 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6293 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6294 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6295 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6296 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6297 if (rsurface.texture->backgroundcurrentskinframe)
6299 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6300 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6301 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6302 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6304 if(rsurface.texture->colormapping)
6306 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6307 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6309 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6310 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6311 R_Mesh_ColorPointer(NULL, 0, 0);
6313 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6315 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6317 // render background
6318 GL_BlendFunc(GL_ONE, GL_ZERO);
6320 GL_AlphaTest(false);
6322 GL_Color(1, 1, 1, 1);
6323 R_Mesh_ColorPointer(NULL, 0, 0);
6325 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6326 if (r_glsl_permutation)
6328 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6329 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6330 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6331 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6332 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6333 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6334 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);
6336 GL_LockArrays(0, 0);
6338 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6339 GL_DepthMask(false);
6340 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6341 R_Mesh_ColorPointer(NULL, 0, 0);
6343 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6344 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6345 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6348 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6349 if (!r_glsl_permutation)
6352 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6353 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6354 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6355 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6356 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6357 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6359 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6361 GL_BlendFunc(GL_ONE, GL_ZERO);
6363 GL_AlphaTest(false);
6367 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6368 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6369 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6372 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6374 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6375 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);
6377 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6381 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6382 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);
6384 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6386 GL_LockArrays(0, 0);
6389 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6391 // OpenGL 1.3 path - anything not completely ancient
6392 int texturesurfaceindex;
6393 qboolean applycolor;
6397 const texturelayer_t *layer;
6398 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6400 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6403 int layertexrgbscale;
6404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6406 if (layerindex == 0)
6410 GL_AlphaTest(false);
6411 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6414 GL_DepthMask(layer->depthmask && writedepth);
6415 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6416 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6418 layertexrgbscale = 4;
6419 VectorScale(layer->color, 0.25f, layercolor);
6421 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6423 layertexrgbscale = 2;
6424 VectorScale(layer->color, 0.5f, layercolor);
6428 layertexrgbscale = 1;
6429 VectorScale(layer->color, 1.0f, layercolor);
6431 layercolor[3] = layer->color[3];
6432 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6433 R_Mesh_ColorPointer(NULL, 0, 0);
6434 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6435 switch (layer->type)
6437 case TEXTURELAYERTYPE_LITTEXTURE:
6438 memset(&m, 0, sizeof(m));
6439 m.tex[0] = R_GetTexture(r_texture_white);
6440 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6441 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6442 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6443 m.tex[1] = R_GetTexture(layer->texture);
6444 m.texmatrix[1] = layer->texmatrix;
6445 m.texrgbscale[1] = layertexrgbscale;
6446 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6447 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6448 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6449 R_Mesh_TextureState(&m);
6450 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6451 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6452 else if (rsurface.uselightmaptexture)
6453 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6455 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6457 case TEXTURELAYERTYPE_TEXTURE:
6458 memset(&m, 0, sizeof(m));
6459 m.tex[0] = R_GetTexture(layer->texture);
6460 m.texmatrix[0] = layer->texmatrix;
6461 m.texrgbscale[0] = layertexrgbscale;
6462 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6463 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6464 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6465 R_Mesh_TextureState(&m);
6466 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6468 case TEXTURELAYERTYPE_FOG:
6469 memset(&m, 0, sizeof(m));
6470 m.texrgbscale[0] = layertexrgbscale;
6473 m.tex[0] = R_GetTexture(layer->texture);
6474 m.texmatrix[0] = layer->texmatrix;
6475 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6476 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6477 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6479 R_Mesh_TextureState(&m);
6480 // generate a color array for the fog pass
6481 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6482 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6487 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)
6489 f = 1 - FogPoint_Model(v);
6490 c[0] = layercolor[0];
6491 c[1] = layercolor[1];
6492 c[2] = layercolor[2];
6493 c[3] = f * layercolor[3];
6496 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6499 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6501 GL_LockArrays(0, 0);
6504 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6506 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6507 GL_AlphaTest(false);
6511 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6513 // OpenGL 1.1 - crusty old voodoo path
6514 int texturesurfaceindex;
6518 const texturelayer_t *layer;
6519 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6521 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6525 if (layerindex == 0)
6529 GL_AlphaTest(false);
6530 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6533 GL_DepthMask(layer->depthmask && writedepth);
6534 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6535 R_Mesh_ColorPointer(NULL, 0, 0);
6536 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6537 switch (layer->type)
6539 case TEXTURELAYERTYPE_LITTEXTURE:
6540 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6542 // two-pass lit texture with 2x rgbscale
6543 // first the lightmap pass
6544 memset(&m, 0, sizeof(m));
6545 m.tex[0] = R_GetTexture(r_texture_white);
6546 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6547 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6548 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6549 R_Mesh_TextureState(&m);
6550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6551 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6552 else if (rsurface.uselightmaptexture)
6553 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6555 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6556 GL_LockArrays(0, 0);
6557 // then apply the texture to it
6558 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6559 memset(&m, 0, sizeof(m));
6560 m.tex[0] = R_GetTexture(layer->texture);
6561 m.texmatrix[0] = layer->texmatrix;
6562 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6563 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6564 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6565 R_Mesh_TextureState(&m);
6566 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);
6570 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6571 memset(&m, 0, sizeof(m));
6572 m.tex[0] = R_GetTexture(layer->texture);
6573 m.texmatrix[0] = layer->texmatrix;
6574 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6575 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6576 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6577 R_Mesh_TextureState(&m);
6578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6579 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);
6581 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);
6584 case TEXTURELAYERTYPE_TEXTURE:
6585 // singletexture unlit texture with transparency support
6586 memset(&m, 0, sizeof(m));
6587 m.tex[0] = R_GetTexture(layer->texture);
6588 m.texmatrix[0] = layer->texmatrix;
6589 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6590 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6591 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6592 R_Mesh_TextureState(&m);
6593 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);
6595 case TEXTURELAYERTYPE_FOG:
6596 // singletexture fogging
6597 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6600 memset(&m, 0, sizeof(m));
6601 m.tex[0] = R_GetTexture(layer->texture);
6602 m.texmatrix[0] = layer->texmatrix;
6603 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6604 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6605 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6606 R_Mesh_TextureState(&m);
6609 R_Mesh_ResetTextureState();
6610 // generate a color array for the fog pass
6611 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6615 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6616 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)
6618 f = 1 - FogPoint_Model(v);
6619 c[0] = layer->color[0];
6620 c[1] = layer->color[1];
6621 c[2] = layer->color[2];
6622 c[3] = f * layer->color[3];
6625 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6628 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6630 GL_LockArrays(0, 0);
6633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6635 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6636 GL_AlphaTest(false);
6640 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6644 GL_AlphaTest(false);
6645 R_Mesh_ColorPointer(NULL, 0, 0);
6646 R_Mesh_ResetTextureState();
6647 R_SetupGenericShader(false);
6649 if(rsurface.texture && rsurface.texture->currentskinframe)
6651 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6652 c[3] *= rsurface.texture->currentalpha;
6662 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6664 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6665 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6666 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6669 // brighten it up (as texture value 127 means "unlit")
6670 c[0] *= 2 * r_refdef.view.colorscale;
6671 c[1] *= 2 * r_refdef.view.colorscale;
6672 c[2] *= 2 * r_refdef.view.colorscale;
6674 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6675 c[3] *= r_wateralpha.value;
6677 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6679 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6680 GL_DepthMask(false);
6682 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6684 GL_BlendFunc(GL_ONE, GL_ONE);
6685 GL_DepthMask(false);
6687 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6689 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6690 GL_DepthMask(false);
6692 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6694 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6695 GL_DepthMask(false);
6699 GL_BlendFunc(GL_ONE, GL_ZERO);
6700 GL_DepthMask(writedepth);
6703 rsurface.lightmapcolor4f = NULL;
6705 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6707 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6709 rsurface.lightmapcolor4f = NULL;
6710 rsurface.lightmapcolor4f_bufferobject = 0;
6711 rsurface.lightmapcolor4f_bufferoffset = 0;
6713 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6715 qboolean applycolor = true;
6718 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6720 r_refdef.lightmapintensity = 1;
6721 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6722 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6726 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6728 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6729 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6730 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6733 if(!rsurface.lightmapcolor4f)
6734 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6736 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6737 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6738 if(r_refdef.fogenabled)
6739 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6741 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6742 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6745 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6748 RSurf_SetupDepthAndCulling();
6749 if (r_showsurfaces.integer == 3)
6750 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6751 else if (r_glsl.integer && gl_support_fragment_shader)
6752 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6753 else if (gl_combine.integer && r_textureunits.integer >= 2)
6754 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6756 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6760 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6763 RSurf_SetupDepthAndCulling();
6764 if (r_showsurfaces.integer == 3)
6765 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6766 else if (r_glsl.integer && gl_support_fragment_shader)
6767 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6768 else if (gl_combine.integer && r_textureunits.integer >= 2)
6769 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6771 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6775 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6778 int texturenumsurfaces, endsurface;
6780 msurface_t *surface;
6781 msurface_t *texturesurfacelist[1024];
6783 // if the model is static it doesn't matter what value we give for
6784 // wantnormals and wanttangents, so this logic uses only rules applicable
6785 // to a model, knowing that they are meaningless otherwise
6786 if (ent == r_refdef.scene.worldentity)
6787 RSurf_ActiveWorldEntity();
6788 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6789 RSurf_ActiveModelEntity(ent, false, false);
6791 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6793 for (i = 0;i < numsurfaces;i = j)
6796 surface = rsurface.modelsurfaces + surfacelist[i];
6797 texture = surface->texture;
6798 rsurface.texture = R_GetCurrentTexture(texture);
6799 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6800 // scan ahead until we find a different texture
6801 endsurface = min(i + 1024, numsurfaces);
6802 texturenumsurfaces = 0;
6803 texturesurfacelist[texturenumsurfaces++] = surface;
6804 for (;j < endsurface;j++)
6806 surface = rsurface.modelsurfaces + surfacelist[j];
6807 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6809 texturesurfacelist[texturenumsurfaces++] = surface;
6811 // render the range of surfaces
6812 if (ent == r_refdef.scene.worldentity)
6813 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6815 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6817 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6818 GL_AlphaTest(false);
6821 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6823 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6827 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6829 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6831 RSurf_SetupDepthAndCulling();
6832 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6833 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6835 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6837 RSurf_SetupDepthAndCulling();
6838 GL_AlphaTest(false);
6839 R_Mesh_ColorPointer(NULL, 0, 0);
6840 R_Mesh_ResetTextureState();
6841 R_SetupGenericShader(false);
6842 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6844 GL_BlendFunc(GL_ONE, GL_ZERO);
6845 GL_Color(0, 0, 0, 1);
6846 GL_DepthTest(writedepth);
6847 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6849 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6851 RSurf_SetupDepthAndCulling();
6852 GL_AlphaTest(false);
6853 R_Mesh_ColorPointer(NULL, 0, 0);
6854 R_Mesh_ResetTextureState();
6855 R_SetupGenericShader(false);
6856 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6858 GL_BlendFunc(GL_ONE, GL_ZERO);
6860 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6862 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6863 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6864 else if (!rsurface.texture->currentnumlayers)
6866 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6868 // transparent surfaces get pushed off into the transparent queue
6869 int surfacelistindex;
6870 const msurface_t *surface;
6871 vec3_t tempcenter, center;
6872 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6874 surface = texturesurfacelist[surfacelistindex];
6875 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6876 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6877 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6878 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6879 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6884 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6885 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6890 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6894 // break the surface list down into batches by texture and use of lightmapping
6895 for (i = 0;i < numsurfaces;i = j)
6898 // texture is the base texture pointer, rsurface.texture is the
6899 // current frame/skin the texture is directing us to use (for example
6900 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6901 // use skin 1 instead)
6902 texture = surfacelist[i]->texture;
6903 rsurface.texture = R_GetCurrentTexture(texture);
6904 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6905 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6907 // if this texture is not the kind we want, skip ahead to the next one
6908 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6912 // simply scan ahead until we find a different texture or lightmap state
6913 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6915 // render the range of surfaces
6916 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6920 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6925 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6927 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6929 RSurf_SetupDepthAndCulling();
6930 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6931 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6933 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6935 RSurf_SetupDepthAndCulling();
6936 GL_AlphaTest(false);
6937 R_Mesh_ColorPointer(NULL, 0, 0);
6938 R_Mesh_ResetTextureState();
6939 R_SetupGenericShader(false);
6940 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6942 GL_BlendFunc(GL_ONE, GL_ZERO);
6943 GL_Color(0, 0, 0, 1);
6944 GL_DepthTest(writedepth);
6945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6947 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6949 RSurf_SetupDepthAndCulling();
6950 GL_AlphaTest(false);
6951 R_Mesh_ColorPointer(NULL, 0, 0);
6952 R_Mesh_ResetTextureState();
6953 R_SetupGenericShader(false);
6954 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6956 GL_BlendFunc(GL_ONE, GL_ZERO);
6958 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6960 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6961 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6962 else if (!rsurface.texture->currentnumlayers)
6964 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6966 // transparent surfaces get pushed off into the transparent queue
6967 int surfacelistindex;
6968 const msurface_t *surface;
6969 vec3_t tempcenter, center;
6970 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6972 surface = texturesurfacelist[surfacelistindex];
6973 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6974 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6975 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6976 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6977 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6982 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6983 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6988 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6992 // break the surface list down into batches by texture and use of lightmapping
6993 for (i = 0;i < numsurfaces;i = j)
6996 // texture is the base texture pointer, rsurface.texture is the
6997 // current frame/skin the texture is directing us to use (for example
6998 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6999 // use skin 1 instead)
7000 texture = surfacelist[i]->texture;
7001 rsurface.texture = R_GetCurrentTexture(texture);
7002 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7003 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7005 // if this texture is not the kind we want, skip ahead to the next one
7006 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7010 // simply scan ahead until we find a different texture or lightmap state
7011 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7013 // render the range of surfaces
7014 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7018 float locboxvertex3f[6*4*3] =
7020 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7021 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7022 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7023 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7024 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7025 1,0,0, 0,0,0, 0,1,0, 1,1,0
7028 unsigned short locboxelements[6*2*3] =
7038 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7041 cl_locnode_t *loc = (cl_locnode_t *)ent;
7043 float vertex3f[6*4*3];
7045 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7046 GL_DepthMask(false);
7047 GL_DepthRange(0, 1);
7048 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7050 GL_CullFace(GL_NONE);
7051 R_Mesh_Matrix(&identitymatrix);
7053 R_Mesh_VertexPointer(vertex3f, 0, 0);
7054 R_Mesh_ColorPointer(NULL, 0, 0);
7055 R_Mesh_ResetTextureState();
7056 R_SetupGenericShader(false);
7059 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7060 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7061 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7062 surfacelist[0] < 0 ? 0.5f : 0.125f);
7064 if (VectorCompare(loc->mins, loc->maxs))
7066 VectorSet(size, 2, 2, 2);
7067 VectorMA(loc->mins, -0.5f, size, mins);
7071 VectorCopy(loc->mins, mins);
7072 VectorSubtract(loc->maxs, loc->mins, size);
7075 for (i = 0;i < 6*4*3;)
7076 for (j = 0;j < 3;j++, i++)
7077 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7079 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7082 void R_DrawLocs(void)
7085 cl_locnode_t *loc, *nearestloc;
7087 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7088 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7090 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7091 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7095 void R_DrawDebugModel(entity_render_t *ent)
7097 int i, j, k, l, flagsmask;
7098 const int *elements;
7100 msurface_t *surface;
7101 dp_model_t *model = ent->model;
7104 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7106 R_Mesh_ColorPointer(NULL, 0, 0);
7107 R_Mesh_ResetTextureState();
7108 R_SetupGenericShader(false);
7109 GL_DepthRange(0, 1);
7110 GL_DepthTest(!r_showdisabledepthtest.integer);
7111 GL_DepthMask(false);
7112 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7114 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7116 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7117 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7119 if (brush->colbrushf && brush->colbrushf->numtriangles)
7121 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7122 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);
7123 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7126 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7128 if (surface->num_collisiontriangles)
7130 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7131 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);
7132 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7137 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7139 if (r_showtris.integer || r_shownormals.integer)
7141 if (r_showdisabledepthtest.integer)
7143 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7144 GL_DepthMask(false);
7148 GL_BlendFunc(GL_ONE, GL_ZERO);
7151 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7153 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7155 rsurface.texture = R_GetCurrentTexture(surface->texture);
7156 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7158 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7159 if (r_showtris.value > 0)
7161 if (!rsurface.texture->currentlayers->depthmask)
7162 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7163 else if (ent == r_refdef.scene.worldentity)
7164 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7166 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7167 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7168 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7169 R_Mesh_ColorPointer(NULL, 0, 0);
7170 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7171 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7172 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7173 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7174 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7177 if (r_shownormals.value < 0)
7180 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7182 VectorCopy(rsurface.vertex3f + l * 3, v);
7183 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7184 qglVertex3f(v[0], v[1], v[2]);
7185 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7186 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7187 qglVertex3f(v[0], v[1], v[2]);
7192 if (r_shownormals.value > 0)
7195 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7197 VectorCopy(rsurface.vertex3f + l * 3, v);
7198 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7199 qglVertex3f(v[0], v[1], v[2]);
7200 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7201 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7202 qglVertex3f(v[0], v[1], v[2]);
7207 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7209 VectorCopy(rsurface.vertex3f + l * 3, v);
7210 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7211 qglVertex3f(v[0], v[1], v[2]);
7212 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7213 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7214 qglVertex3f(v[0], v[1], v[2]);
7219 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7221 VectorCopy(rsurface.vertex3f + l * 3, v);
7222 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7223 qglVertex3f(v[0], v[1], v[2]);
7224 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7225 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7226 qglVertex3f(v[0], v[1], v[2]);
7233 rsurface.texture = NULL;
7237 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7238 int r_maxsurfacelist = 0;
7239 msurface_t **r_surfacelist = NULL;
7240 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7242 int i, j, endj, f, flagsmask;
7244 dp_model_t *model = r_refdef.scene.worldmodel;
7245 msurface_t *surfaces;
7246 unsigned char *update;
7247 int numsurfacelist = 0;
7251 if (r_maxsurfacelist < model->num_surfaces)
7253 r_maxsurfacelist = model->num_surfaces;
7255 Mem_Free(r_surfacelist);
7256 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7259 RSurf_ActiveWorldEntity();
7261 surfaces = model->data_surfaces;
7262 update = model->brushq1.lightmapupdateflags;
7264 // update light styles on this submodel
7265 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7267 model_brush_lightstyleinfo_t *style;
7268 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7270 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7272 int *list = style->surfacelist;
7273 style->value = r_refdef.scene.lightstylevalue[style->style];
7274 for (j = 0;j < style->numsurfaces;j++)
7275 update[list[j]] = true;
7280 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7284 R_DrawDebugModel(r_refdef.scene.worldentity);
7285 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7291 rsurface.uselightmaptexture = false;
7292 rsurface.texture = NULL;
7293 rsurface.rtlight = NULL;
7295 // add visible surfaces to draw list
7296 for (i = 0;i < model->nummodelsurfaces;i++)
7298 j = model->sortedmodelsurfaces[i];
7299 if (r_refdef.viewcache.world_surfacevisible[j])
7300 r_surfacelist[numsurfacelist++] = surfaces + j;
7302 // update lightmaps if needed
7304 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7305 if (r_refdef.viewcache.world_surfacevisible[j])
7307 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7308 // don't do anything if there were no surfaces
7309 if (!numsurfacelist)
7311 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7314 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7315 GL_AlphaTest(false);
7317 // add to stats if desired
7318 if (r_speeds.integer && !skysurfaces && !depthonly)
7320 r_refdef.stats.world_surfaces += numsurfacelist;
7321 for (j = 0;j < numsurfacelist;j++)
7322 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7324 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7327 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7329 int i, j, endj, f, flagsmask;
7331 dp_model_t *model = ent->model;
7332 msurface_t *surfaces;
7333 unsigned char *update;
7334 int numsurfacelist = 0;
7338 if (r_maxsurfacelist < model->num_surfaces)
7340 r_maxsurfacelist = model->num_surfaces;
7342 Mem_Free(r_surfacelist);
7343 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7346 // if the model is static it doesn't matter what value we give for
7347 // wantnormals and wanttangents, so this logic uses only rules applicable
7348 // to a model, knowing that they are meaningless otherwise
7349 if (ent == r_refdef.scene.worldentity)
7350 RSurf_ActiveWorldEntity();
7351 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7352 RSurf_ActiveModelEntity(ent, false, false);
7354 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7356 surfaces = model->data_surfaces;
7357 update = model->brushq1.lightmapupdateflags;
7359 // update light styles
7360 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7362 model_brush_lightstyleinfo_t *style;
7363 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7365 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7367 int *list = style->surfacelist;
7368 style->value = r_refdef.scene.lightstylevalue[style->style];
7369 for (j = 0;j < style->numsurfaces;j++)
7370 update[list[j]] = true;
7375 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7379 R_DrawDebugModel(ent);
7380 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7386 rsurface.uselightmaptexture = false;
7387 rsurface.texture = NULL;
7388 rsurface.rtlight = NULL;
7390 // add visible surfaces to draw list
7391 for (i = 0;i < model->nummodelsurfaces;i++)
7392 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7393 // don't do anything if there were no surfaces
7394 if (!numsurfacelist)
7396 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7399 // update lightmaps if needed
7401 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7403 R_BuildLightMap(ent, surfaces + j);
7404 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7405 GL_AlphaTest(false);
7407 // add to stats if desired
7408 if (r_speeds.integer && !skysurfaces && !depthonly)
7410 r_refdef.stats.entities_surfaces += numsurfacelist;
7411 for (j = 0;j < numsurfacelist;j++)
7412 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7414 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity