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 frame-by-frame alpha control {0 to 1} - 0.7 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage; requires r_motionblur to have a value"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "velocity at which there is minimum blur"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "velocity at which there is full blur"};
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_vtime = {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 the alpha level of the motion blur variable"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.01", "randomizing coefficient to fix 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; // 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 // initialize the samplers to refer to the texture units we use
1425 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1426 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1427 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1428 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1429 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1430 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1431 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1432 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1433 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1434 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1435 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1436 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1437 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1438 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1439 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1440 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1441 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1442 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1443 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1444 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1446 if (developer.integer)
1447 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1450 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1454 Mem_Free(vertexstring);
1456 Mem_Free(geometrystring);
1458 Mem_Free(fragmentstring);
1461 void R_GLSL_Restart_f(void)
1464 unsigned int permutation;
1465 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1466 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1467 if (r_glsl_permutations[mode][permutation].program)
1468 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1469 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1472 void R_GLSL_DumpShader_f(void)
1476 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1479 Con_Printf("failed to write to glsl/default.glsl\n");
1483 FS_Print(file, "// The engine may define the following macros:\n");
1484 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1485 for (i = 0;i < SHADERMODE_COUNT;i++)
1486 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1487 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1488 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1489 FS_Print(file, "\n");
1490 FS_Print(file, builtinshaderstring);
1493 Con_Printf("glsl/default.glsl written\n");
1496 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1498 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1499 if (r_glsl_permutation != perm)
1501 r_glsl_permutation = perm;
1502 if (!r_glsl_permutation->program)
1504 if (!r_glsl_permutation->compiled)
1505 R_GLSL_CompilePermutation(mode, permutation);
1506 if (!r_glsl_permutation->program)
1508 // remove features until we find a valid permutation
1510 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1512 // reduce i more quickly whenever it would not remove any bits
1513 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1514 if (!(permutation & j))
1517 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1518 if (!r_glsl_permutation->compiled)
1519 R_GLSL_CompilePermutation(mode, permutation);
1520 if (r_glsl_permutation->program)
1523 if (i >= SHADERPERMUTATION_COUNT)
1525 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");
1526 Cvar_SetValueQuick(&r_glsl, 0);
1527 R_GLSL_Restart_f(); // unload shaders
1528 return; // no bit left to clear
1533 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1537 void R_SetupGenericShader(qboolean usetexture)
1539 if (gl_support_fragment_shader)
1541 if (r_glsl.integer && r_glsl_usegeneric.integer)
1542 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1543 else if (r_glsl_permutation)
1545 r_glsl_permutation = NULL;
1546 qglUseProgramObjectARB(0);CHECKGLERROR
1551 void R_SetupGenericTwoTextureShader(int texturemode)
1553 if (gl_support_fragment_shader)
1555 if (r_glsl.integer && r_glsl_usegeneric.integer)
1556 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))));
1557 else if (r_glsl_permutation)
1559 r_glsl_permutation = NULL;
1560 qglUseProgramObjectARB(0);CHECKGLERROR
1563 if (!r_glsl_permutation)
1565 if (texturemode == GL_DECAL && gl_combine.integer)
1566 texturemode = GL_INTERPOLATE_ARB;
1567 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1571 void R_SetupDepthOrShadowShader(void)
1573 if (gl_support_fragment_shader)
1575 if (r_glsl.integer && r_glsl_usegeneric.integer)
1576 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1577 else if (r_glsl_permutation)
1579 r_glsl_permutation = NULL;
1580 qglUseProgramObjectARB(0);CHECKGLERROR
1585 extern rtexture_t *r_shadow_attenuationgradienttexture;
1586 extern rtexture_t *r_shadow_attenuation2dtexture;
1587 extern rtexture_t *r_shadow_attenuation3dtexture;
1588 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1590 // select a permutation of the lighting shader appropriate to this
1591 // combination of texture, entity, light source, and fogging, only use the
1592 // minimum features necessary to avoid wasting rendering time in the
1593 // fragment shader on features that are not being used
1594 unsigned int permutation = 0;
1595 unsigned int mode = 0;
1596 // TODO: implement geometry-shader based shadow volumes someday
1597 if (r_glsl_offsetmapping.integer)
1599 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1600 if (r_glsl_offsetmapping_reliefmapping.integer)
1601 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1603 if (rsurfacepass == RSURFPASS_BACKGROUND)
1605 // distorted background
1606 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1607 mode = SHADERMODE_WATER;
1609 mode = SHADERMODE_REFRACTION;
1611 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1614 mode = SHADERMODE_LIGHTSOURCE;
1615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1616 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1617 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1618 permutation |= SHADERPERMUTATION_CUBEFILTER;
1619 if (diffusescale > 0)
1620 permutation |= SHADERPERMUTATION_DIFFUSE;
1621 if (specularscale > 0)
1622 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1623 if (r_refdef.fogenabled)
1624 permutation |= SHADERPERMUTATION_FOG;
1625 if (rsurface.texture->colormapping)
1626 permutation |= SHADERPERMUTATION_COLORMAPPING;
1627 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1628 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1630 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1632 // unshaded geometry (fullbright or ambient model lighting)
1633 mode = SHADERMODE_FLATCOLOR;
1634 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1635 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1636 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1637 permutation |= SHADERPERMUTATION_GLOW;
1638 if (r_refdef.fogenabled)
1639 permutation |= SHADERPERMUTATION_FOG;
1640 if (rsurface.texture->colormapping)
1641 permutation |= SHADERPERMUTATION_COLORMAPPING;
1642 if (r_glsl_offsetmapping.integer)
1644 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1645 if (r_glsl_offsetmapping_reliefmapping.integer)
1646 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1648 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1649 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1650 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1651 permutation |= SHADERPERMUTATION_REFLECTION;
1653 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1655 // directional model lighting
1656 mode = SHADERMODE_LIGHTDIRECTION;
1657 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1658 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1659 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1660 permutation |= SHADERPERMUTATION_GLOW;
1661 permutation |= SHADERPERMUTATION_DIFFUSE;
1662 if (specularscale > 0)
1663 permutation |= SHADERPERMUTATION_SPECULAR;
1664 if (r_refdef.fogenabled)
1665 permutation |= SHADERPERMUTATION_FOG;
1666 if (rsurface.texture->colormapping)
1667 permutation |= SHADERPERMUTATION_COLORMAPPING;
1668 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1669 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1670 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1671 permutation |= SHADERPERMUTATION_REFLECTION;
1673 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1675 // ambient model lighting
1676 mode = SHADERMODE_LIGHTDIRECTION;
1677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1678 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1679 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1680 permutation |= SHADERPERMUTATION_GLOW;
1681 if (r_refdef.fogenabled)
1682 permutation |= SHADERPERMUTATION_FOG;
1683 if (rsurface.texture->colormapping)
1684 permutation |= SHADERPERMUTATION_COLORMAPPING;
1685 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1686 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1687 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1688 permutation |= SHADERPERMUTATION_REFLECTION;
1693 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1695 // deluxemapping (light direction texture)
1696 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1697 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1699 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1700 permutation |= SHADERPERMUTATION_DIFFUSE;
1701 if (specularscale > 0)
1702 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1704 else if (r_glsl_deluxemapping.integer >= 2)
1706 // fake deluxemapping (uniform light direction in tangentspace)
1707 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1708 permutation |= SHADERPERMUTATION_DIFFUSE;
1709 if (specularscale > 0)
1710 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1712 else if (rsurface.uselightmaptexture)
1714 // ordinary lightmapping (q1bsp, q3bsp)
1715 mode = SHADERMODE_LIGHTMAP;
1719 // ordinary vertex coloring (q3bsp)
1720 mode = SHADERMODE_VERTEXCOLOR;
1722 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1723 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1724 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1725 permutation |= SHADERPERMUTATION_GLOW;
1726 if (r_refdef.fogenabled)
1727 permutation |= SHADERPERMUTATION_FOG;
1728 if (rsurface.texture->colormapping)
1729 permutation |= SHADERPERMUTATION_COLORMAPPING;
1730 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1731 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1732 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1733 permutation |= SHADERPERMUTATION_REFLECTION;
1735 if(permutation & SHADERPERMUTATION_SPECULAR)
1736 if(r_shadow_glossexact.integer)
1737 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1738 R_SetupShader_SetPermutation(mode, permutation);
1739 if (mode == SHADERMODE_LIGHTSOURCE)
1741 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1742 if (permutation & SHADERPERMUTATION_DIFFUSE)
1744 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1745 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1746 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1747 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1751 // ambient only is simpler
1752 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]);
1753 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1754 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1755 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1757 // additive passes are only darkened by fog, not tinted
1758 if (r_glsl_permutation->loc_FogColor >= 0)
1759 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1763 if (mode == SHADERMODE_LIGHTDIRECTION)
1765 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);
1766 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);
1767 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);
1768 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]);
1772 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1773 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1774 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1776 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]);
1777 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1778 // additive passes are only darkened by fog, not tinted
1779 if (r_glsl_permutation->loc_FogColor >= 0)
1781 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1782 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1784 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1786 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);
1787 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]);
1788 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]);
1789 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1790 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1791 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1792 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1794 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1796 // The formula used is actually:
1797 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1798 // color.rgb *= SceneBrightness;
1800 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1801 // and do [[calculations]] here in the engine
1802 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1803 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1806 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1807 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1808 if (r_glsl_permutation->loc_Color_Pants >= 0)
1810 if (rsurface.texture->currentskinframe->pants)
1811 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1813 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1815 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1817 if (rsurface.texture->currentskinframe->shirt)
1818 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1820 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1822 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1823 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1825 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1829 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1831 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1835 #define SKINFRAME_HASH 1024
1839 int loadsequence; // incremented each level change
1840 memexpandablearray_t array;
1841 skinframe_t *hash[SKINFRAME_HASH];
1844 r_skinframe_t r_skinframe;
1846 void R_SkinFrame_PrepareForPurge(void)
1848 r_skinframe.loadsequence++;
1849 // wrap it without hitting zero
1850 if (r_skinframe.loadsequence >= 200)
1851 r_skinframe.loadsequence = 1;
1854 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1858 // mark the skinframe as used for the purging code
1859 skinframe->loadsequence = r_skinframe.loadsequence;
1862 void R_SkinFrame_Purge(void)
1866 for (i = 0;i < SKINFRAME_HASH;i++)
1868 for (s = r_skinframe.hash[i];s;s = s->next)
1870 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1872 if (s->merged == s->base)
1874 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1875 R_PurgeTexture(s->stain );s->stain = NULL;
1876 R_PurgeTexture(s->merged);s->merged = NULL;
1877 R_PurgeTexture(s->base );s->base = NULL;
1878 R_PurgeTexture(s->pants );s->pants = NULL;
1879 R_PurgeTexture(s->shirt );s->shirt = NULL;
1880 R_PurgeTexture(s->nmap );s->nmap = NULL;
1881 R_PurgeTexture(s->gloss );s->gloss = NULL;
1882 R_PurgeTexture(s->glow );s->glow = NULL;
1883 R_PurgeTexture(s->fog );s->fog = NULL;
1884 s->loadsequence = 0;
1890 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1892 char basename[MAX_QPATH];
1894 Image_StripImageExtension(name, basename, sizeof(basename));
1896 if( last == NULL ) {
1898 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1899 item = r_skinframe.hash[hashindex];
1904 // linearly search through the hash bucket
1905 for( ; item ; item = item->next ) {
1906 if( !strcmp( item->basename, basename ) ) {
1913 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1917 char basename[MAX_QPATH];
1919 Image_StripImageExtension(name, basename, sizeof(basename));
1921 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1922 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1923 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1927 rtexture_t *dyntexture;
1928 // check whether its a dynamic texture
1929 dyntexture = CL_GetDynTexture( basename );
1930 if (!add && !dyntexture)
1932 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1933 memset(item, 0, sizeof(*item));
1934 strlcpy(item->basename, basename, sizeof(item->basename));
1935 item->base = dyntexture; // either NULL or dyntexture handle
1936 item->textureflags = textureflags;
1937 item->comparewidth = comparewidth;
1938 item->compareheight = compareheight;
1939 item->comparecrc = comparecrc;
1940 item->next = r_skinframe.hash[hashindex];
1941 r_skinframe.hash[hashindex] = item;
1943 else if( item->base == NULL )
1945 rtexture_t *dyntexture;
1946 // check whether its a dynamic texture
1947 // 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]
1948 dyntexture = CL_GetDynTexture( basename );
1949 item->base = dyntexture; // either NULL or dyntexture handle
1952 R_SkinFrame_MarkUsed(item);
1956 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1958 unsigned long long avgcolor[5], wsum; \
1966 for(pix = 0; pix < cnt; ++pix) \
1969 for(comp = 0; comp < 3; ++comp) \
1971 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1974 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1976 for(comp = 0; comp < 3; ++comp) \
1977 avgcolor[comp] += getpixel * w; \
1980 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1981 avgcolor[4] += getpixel; \
1983 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1985 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1986 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1987 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1988 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1991 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1993 // FIXME: it should be possible to disable loading various layers using
1994 // cvars, to prevent wasted loading time and memory usage if the user does
1996 qboolean loadnormalmap = true;
1997 qboolean loadgloss = true;
1998 qboolean loadpantsandshirt = true;
1999 qboolean loadglow = true;
2001 unsigned char *pixels;
2002 unsigned char *bumppixels;
2003 unsigned char *basepixels = NULL;
2004 int basepixels_width;
2005 int basepixels_height;
2006 skinframe_t *skinframe;
2010 if (cls.state == ca_dedicated)
2013 // return an existing skinframe if already loaded
2014 // if loading of the first image fails, don't make a new skinframe as it
2015 // would cause all future lookups of this to be missing
2016 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2017 if (skinframe && skinframe->base)
2020 basepixels = loadimagepixelsbgra(name, complain, true);
2021 if (basepixels == NULL)
2024 if (developer_loading.integer)
2025 Con_Printf("loading skin \"%s\"\n", name);
2027 // we've got some pixels to store, so really allocate this new texture now
2029 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2030 skinframe->stain = NULL;
2031 skinframe->merged = NULL;
2032 skinframe->base = r_texture_notexture;
2033 skinframe->pants = NULL;
2034 skinframe->shirt = NULL;
2035 skinframe->nmap = r_texture_blanknormalmap;
2036 skinframe->gloss = NULL;
2037 skinframe->glow = NULL;
2038 skinframe->fog = NULL;
2040 basepixels_width = image_width;
2041 basepixels_height = image_height;
2042 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);
2044 if (textureflags & TEXF_ALPHA)
2046 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2047 if (basepixels[j] < 255)
2049 if (j < basepixels_width * basepixels_height * 4)
2051 // has transparent pixels
2053 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2054 for (j = 0;j < image_width * image_height * 4;j += 4)
2059 pixels[j+3] = basepixels[j+3];
2061 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);
2066 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2067 //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]);
2069 // _norm is the name used by tenebrae and has been adopted as standard
2072 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2074 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);
2078 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2080 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2081 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2082 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);
2084 Mem_Free(bumppixels);
2086 else if (r_shadow_bumpscale_basetexture.value > 0)
2088 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2089 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2090 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);
2094 // _luma is supported for tenebrae compatibility
2095 // (I think it's a very stupid name, but oh well)
2096 // _glow is the preferred name
2097 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;}
2098 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;}
2099 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;}
2100 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;}
2103 Mem_Free(basepixels);
2108 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2111 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2114 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)
2119 for (i = 0;i < width*height;i++)
2120 if (((unsigned char *)&palette[in[i]])[3] > 0)
2122 if (i == width*height)
2125 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2128 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2129 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2132 unsigned char *temp1, *temp2;
2133 skinframe_t *skinframe;
2135 if (cls.state == ca_dedicated)
2138 // if already loaded just return it, otherwise make a new skinframe
2139 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2140 if (skinframe && skinframe->base)
2143 skinframe->stain = NULL;
2144 skinframe->merged = NULL;
2145 skinframe->base = r_texture_notexture;
2146 skinframe->pants = NULL;
2147 skinframe->shirt = NULL;
2148 skinframe->nmap = r_texture_blanknormalmap;
2149 skinframe->gloss = NULL;
2150 skinframe->glow = NULL;
2151 skinframe->fog = NULL;
2153 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2157 if (developer_loading.integer)
2158 Con_Printf("loading 32bit skin \"%s\"\n", name);
2160 if (r_shadow_bumpscale_basetexture.value > 0)
2162 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2163 temp2 = temp1 + width * height * 4;
2164 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2165 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2168 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2169 if (textureflags & TEXF_ALPHA)
2171 for (i = 3;i < width * height * 4;i += 4)
2172 if (skindata[i] < 255)
2174 if (i < width * height * 4)
2176 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2177 memcpy(fogpixels, skindata, width * height * 4);
2178 for (i = 0;i < width * height * 4;i += 4)
2179 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2180 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2181 Mem_Free(fogpixels);
2185 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2186 //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]);
2191 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2194 unsigned char *temp1, *temp2;
2195 unsigned int *palette;
2196 skinframe_t *skinframe;
2198 if (cls.state == ca_dedicated)
2201 // if already loaded just return it, otherwise make a new skinframe
2202 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2203 if (skinframe && skinframe->base)
2206 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2208 skinframe->stain = NULL;
2209 skinframe->merged = NULL;
2210 skinframe->base = r_texture_notexture;
2211 skinframe->pants = NULL;
2212 skinframe->shirt = NULL;
2213 skinframe->nmap = r_texture_blanknormalmap;
2214 skinframe->gloss = NULL;
2215 skinframe->glow = NULL;
2216 skinframe->fog = NULL;
2218 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2222 if (developer_loading.integer)
2223 Con_Printf("loading quake skin \"%s\"\n", name);
2225 if (r_shadow_bumpscale_basetexture.value > 0)
2227 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2228 temp2 = temp1 + width * height * 4;
2229 // use either a custom palette or the quake palette
2230 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2231 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2232 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2235 // use either a custom palette, or the quake palette
2236 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2237 if (loadglowtexture)
2238 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2239 if (loadpantsandshirt)
2241 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2242 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2244 if (skinframe->pants || skinframe->shirt)
2245 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
2246 if (textureflags & TEXF_ALPHA)
2248 for (i = 0;i < width * height;i++)
2249 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2251 if (i < width * height)
2252 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2255 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2256 //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]);
2261 skinframe_t *R_SkinFrame_LoadMissing(void)
2263 skinframe_t *skinframe;
2265 if (cls.state == ca_dedicated)
2268 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2269 skinframe->stain = NULL;
2270 skinframe->merged = NULL;
2271 skinframe->base = r_texture_notexture;
2272 skinframe->pants = NULL;
2273 skinframe->shirt = NULL;
2274 skinframe->nmap = r_texture_blanknormalmap;
2275 skinframe->gloss = NULL;
2276 skinframe->glow = NULL;
2277 skinframe->fog = NULL;
2279 skinframe->avgcolor[0] = rand() / RAND_MAX;
2280 skinframe->avgcolor[1] = rand() / RAND_MAX;
2281 skinframe->avgcolor[2] = rand() / RAND_MAX;
2282 skinframe->avgcolor[3] = 1;
2287 void gl_main_start(void)
2291 memset(r_queries, 0, sizeof(r_queries));
2293 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2294 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2296 // set up r_skinframe loading system for textures
2297 memset(&r_skinframe, 0, sizeof(r_skinframe));
2298 r_skinframe.loadsequence = 1;
2299 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2301 r_main_texturepool = R_AllocTexturePool();
2302 R_BuildBlankTextures();
2304 if (gl_texturecubemap)
2307 R_BuildNormalizationCube();
2309 r_texture_fogattenuation = NULL;
2310 r_texture_gammaramps = NULL;
2311 //r_texture_fogintensity = NULL;
2312 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2313 memset(&r_waterstate, 0, sizeof(r_waterstate));
2314 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2315 memset(&r_svbsp, 0, sizeof (r_svbsp));
2317 r_refdef.fogmasktable_density = 0;
2320 extern rtexture_t *loadingscreentexture;
2321 void gl_main_shutdown(void)
2324 qglDeleteQueriesARB(r_maxqueries, r_queries);
2328 memset(r_queries, 0, sizeof(r_queries));
2330 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2331 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2333 // clear out the r_skinframe state
2334 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2335 memset(&r_skinframe, 0, sizeof(r_skinframe));
2338 Mem_Free(r_svbsp.nodes);
2339 memset(&r_svbsp, 0, sizeof (r_svbsp));
2340 R_FreeTexturePool(&r_main_texturepool);
2341 loadingscreentexture = NULL;
2342 r_texture_blanknormalmap = NULL;
2343 r_texture_white = NULL;
2344 r_texture_grey128 = NULL;
2345 r_texture_black = NULL;
2346 r_texture_whitecube = NULL;
2347 r_texture_normalizationcube = NULL;
2348 r_texture_fogattenuation = NULL;
2349 r_texture_gammaramps = NULL;
2350 //r_texture_fogintensity = NULL;
2351 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2352 memset(&r_waterstate, 0, sizeof(r_waterstate));
2356 extern void CL_ParseEntityLump(char *entitystring);
2357 void gl_main_newmap(void)
2359 // FIXME: move this code to client
2361 char *entities, entname[MAX_QPATH];
2364 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2365 l = (int)strlen(entname) - 4;
2366 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2368 memcpy(entname + l, ".ent", 5);
2369 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2371 CL_ParseEntityLump(entities);
2376 if (cl.worldmodel->brush.entities)
2377 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2381 void GL_Main_Init(void)
2383 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2385 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2386 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2387 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2388 if (gamemode == GAME_NEHAHRA)
2390 Cvar_RegisterVariable (&gl_fogenable);
2391 Cvar_RegisterVariable (&gl_fogdensity);
2392 Cvar_RegisterVariable (&gl_fogred);
2393 Cvar_RegisterVariable (&gl_foggreen);
2394 Cvar_RegisterVariable (&gl_fogblue);
2395 Cvar_RegisterVariable (&gl_fogstart);
2396 Cvar_RegisterVariable (&gl_fogend);
2397 Cvar_RegisterVariable (&gl_skyclip);
2399 Cvar_RegisterVariable(&r_motionblur);
2400 Cvar_RegisterVariable(&r_motionblur_maxblur);
2401 Cvar_RegisterVariable(&r_motionblur_bmin);
2402 Cvar_RegisterVariable(&r_motionblur_vmin);
2403 Cvar_RegisterVariable(&r_motionblur_vmax);
2404 Cvar_RegisterVariable(&r_motionblur_vtime);
2405 Cvar_RegisterVariable(&r_motionblur_randomize);
2406 Cvar_RegisterVariable(&r_damageblur);
2407 Cvar_RegisterVariable(&r_motionblur_debug);
2408 Cvar_RegisterVariable(&r_depthfirst);
2409 Cvar_RegisterVariable(&r_useinfinitefarclip);
2410 Cvar_RegisterVariable(&r_nearclip);
2411 Cvar_RegisterVariable(&r_showbboxes);
2412 Cvar_RegisterVariable(&r_showsurfaces);
2413 Cvar_RegisterVariable(&r_showtris);
2414 Cvar_RegisterVariable(&r_shownormals);
2415 Cvar_RegisterVariable(&r_showlighting);
2416 Cvar_RegisterVariable(&r_showshadowvolumes);
2417 Cvar_RegisterVariable(&r_showcollisionbrushes);
2418 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2419 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2420 Cvar_RegisterVariable(&r_showdisabledepthtest);
2421 Cvar_RegisterVariable(&r_drawportals);
2422 Cvar_RegisterVariable(&r_drawentities);
2423 Cvar_RegisterVariable(&r_cullentities_trace);
2424 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2425 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2426 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2427 Cvar_RegisterVariable(&r_drawviewmodel);
2428 Cvar_RegisterVariable(&r_speeds);
2429 Cvar_RegisterVariable(&r_fullbrights);
2430 Cvar_RegisterVariable(&r_wateralpha);
2431 Cvar_RegisterVariable(&r_dynamic);
2432 Cvar_RegisterVariable(&r_fullbright);
2433 Cvar_RegisterVariable(&r_shadows);
2434 Cvar_RegisterVariable(&r_shadows_throwdistance);
2435 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2436 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2437 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2438 Cvar_RegisterVariable(&r_fog_exp2);
2439 Cvar_RegisterVariable(&r_drawfog);
2440 Cvar_RegisterVariable(&r_textureunits);
2441 Cvar_RegisterVariable(&r_glsl);
2442 Cvar_RegisterVariable(&r_glsl_contrastboost);
2443 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2444 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2445 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2446 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2447 Cvar_RegisterVariable(&r_glsl_postprocess);
2448 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2449 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2450 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2451 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2452 Cvar_RegisterVariable(&r_glsl_usegeneric);
2453 Cvar_RegisterVariable(&r_water);
2454 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2455 Cvar_RegisterVariable(&r_water_clippingplanebias);
2456 Cvar_RegisterVariable(&r_water_refractdistort);
2457 Cvar_RegisterVariable(&r_water_reflectdistort);
2458 Cvar_RegisterVariable(&r_lerpsprites);
2459 Cvar_RegisterVariable(&r_lerpmodels);
2460 Cvar_RegisterVariable(&r_lerplightstyles);
2461 Cvar_RegisterVariable(&r_waterscroll);
2462 Cvar_RegisterVariable(&r_bloom);
2463 Cvar_RegisterVariable(&r_bloom_colorscale);
2464 Cvar_RegisterVariable(&r_bloom_brighten);
2465 Cvar_RegisterVariable(&r_bloom_blur);
2466 Cvar_RegisterVariable(&r_bloom_resolution);
2467 Cvar_RegisterVariable(&r_bloom_colorexponent);
2468 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2469 Cvar_RegisterVariable(&r_hdr);
2470 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2471 Cvar_RegisterVariable(&r_hdr_glowintensity);
2472 Cvar_RegisterVariable(&r_hdr_range);
2473 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2474 Cvar_RegisterVariable(&developer_texturelogging);
2475 Cvar_RegisterVariable(&gl_lightmaps);
2476 Cvar_RegisterVariable(&r_test);
2477 Cvar_RegisterVariable(&r_batchmode);
2478 Cvar_RegisterVariable(&r_glsl_saturation);
2479 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2480 Cvar_SetValue("r_fullbrights", 0);
2481 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2483 Cvar_RegisterVariable(&r_track_sprites);
2484 Cvar_RegisterVariable(&r_track_sprites_flags);
2485 Cvar_RegisterVariable(&r_track_sprites_scalew);
2486 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2489 extern void R_Textures_Init(void);
2490 extern void GL_Draw_Init(void);
2491 extern void GL_Main_Init(void);
2492 extern void R_Shadow_Init(void);
2493 extern void R_Sky_Init(void);
2494 extern void GL_Surf_Init(void);
2495 extern void R_Particles_Init(void);
2496 extern void R_Explosion_Init(void);
2497 extern void gl_backend_init(void);
2498 extern void Sbar_Init(void);
2499 extern void R_LightningBeams_Init(void);
2500 extern void Mod_RenderInit(void);
2502 void Render_Init(void)
2514 R_LightningBeams_Init();
2523 extern char *ENGINE_EXTENSIONS;
2526 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2527 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2528 gl_version = (const char *)qglGetString(GL_VERSION);
2529 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2533 if (!gl_platformextensions)
2534 gl_platformextensions = "";
2536 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2537 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2538 Con_Printf("GL_VERSION: %s\n", gl_version);
2539 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2540 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2542 VID_CheckExtensions();
2544 // LordHavoc: report supported extensions
2545 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2547 // clear to black (loading plaque will be seen over this)
2549 qglClearColor(0,0,0,1);CHECKGLERROR
2550 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2553 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2557 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2559 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2562 p = r_refdef.view.frustum + i;
2567 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2571 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2575 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2579 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2583 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2587 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2591 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2595 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2603 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2607 for (i = 0;i < numplanes;i++)
2614 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2618 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2622 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2626 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2630 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2634 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2638 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2642 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2650 //==================================================================================
2652 static void R_View_UpdateEntityLighting (void)
2655 entity_render_t *ent;
2656 vec3_t tempdiffusenormal;
2658 for (i = 0;i < r_refdef.scene.numentities;i++)
2660 ent = r_refdef.scene.entities[i];
2662 // skip unseen models
2663 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2667 if (ent->model && ent->model->brush.num_leafs)
2669 // TODO: use modellight for r_ambient settings on world?
2670 VectorSet(ent->modellight_ambient, 0, 0, 0);
2671 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2672 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2676 // fetch the lighting from the worldmodel data
2677 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));
2678 VectorClear(ent->modellight_diffuse);
2679 VectorClear(tempdiffusenormal);
2680 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2683 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2684 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2687 VectorSet(ent->modellight_ambient, 1, 1, 1);
2689 // move the light direction into modelspace coordinates for lighting code
2690 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2691 if(VectorLength2(ent->modellight_lightdir) == 0)
2692 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2693 VectorNormalize(ent->modellight_lightdir);
2697 static void R_View_UpdateEntityVisible (void)
2700 entity_render_t *ent;
2702 if (!r_drawentities.integer)
2705 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2706 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2708 // worldmodel can check visibility
2709 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2710 for (i = 0;i < r_refdef.scene.numentities;i++)
2712 ent = r_refdef.scene.entities[i];
2713 if (!(ent->flags & renderimask))
2714 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)))
2715 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))
2716 r_refdef.viewcache.entityvisible[i] = true;
2718 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2720 for (i = 0;i < r_refdef.scene.numentities;i++)
2722 ent = r_refdef.scene.entities[i];
2723 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2725 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))
2726 ent->last_trace_visibility = realtime;
2727 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2728 r_refdef.viewcache.entityvisible[i] = 0;
2735 // no worldmodel or it can't check visibility
2736 for (i = 0;i < r_refdef.scene.numentities;i++)
2738 ent = r_refdef.scene.entities[i];
2739 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));
2744 // only used if skyrendermasked, and normally returns false
2745 int R_DrawBrushModelsSky (void)
2748 entity_render_t *ent;
2750 if (!r_drawentities.integer)
2754 for (i = 0;i < r_refdef.scene.numentities;i++)
2756 if (!r_refdef.viewcache.entityvisible[i])
2758 ent = r_refdef.scene.entities[i];
2759 if (!ent->model || !ent->model->DrawSky)
2761 ent->model->DrawSky(ent);
2767 static void R_DrawNoModel(entity_render_t *ent);
2768 static void R_DrawModels(void)
2771 entity_render_t *ent;
2773 if (!r_drawentities.integer)
2776 for (i = 0;i < r_refdef.scene.numentities;i++)
2778 if (!r_refdef.viewcache.entityvisible[i])
2780 ent = r_refdef.scene.entities[i];
2781 r_refdef.stats.entities++;
2782 if (ent->model && ent->model->Draw != NULL)
2783 ent->model->Draw(ent);
2789 static void R_DrawModelsDepth(void)
2792 entity_render_t *ent;
2794 if (!r_drawentities.integer)
2797 for (i = 0;i < r_refdef.scene.numentities;i++)
2799 if (!r_refdef.viewcache.entityvisible[i])
2801 ent = r_refdef.scene.entities[i];
2802 if (ent->model && ent->model->DrawDepth != NULL)
2803 ent->model->DrawDepth(ent);
2807 static void R_DrawModelsDebug(void)
2810 entity_render_t *ent;
2812 if (!r_drawentities.integer)
2815 for (i = 0;i < r_refdef.scene.numentities;i++)
2817 if (!r_refdef.viewcache.entityvisible[i])
2819 ent = r_refdef.scene.entities[i];
2820 if (ent->model && ent->model->DrawDebug != NULL)
2821 ent->model->DrawDebug(ent);
2825 static void R_DrawModelsAddWaterPlanes(void)
2828 entity_render_t *ent;
2830 if (!r_drawentities.integer)
2833 for (i = 0;i < r_refdef.scene.numentities;i++)
2835 if (!r_refdef.viewcache.entityvisible[i])
2837 ent = r_refdef.scene.entities[i];
2838 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2839 ent->model->DrawAddWaterPlanes(ent);
2843 static void R_View_SetFrustum(void)
2846 double slopex, slopey;
2847 vec3_t forward, left, up, origin;
2849 // we can't trust r_refdef.view.forward and friends in reflected scenes
2850 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2853 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2854 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2855 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2856 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2857 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2858 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2859 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2860 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2861 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2862 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2863 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2864 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2868 zNear = r_refdef.nearclip;
2869 nudge = 1.0 - 1.0 / (1<<23);
2870 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2871 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2872 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2873 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2874 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2875 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2876 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2877 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2883 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2884 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2885 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2886 r_refdef.view.frustum[0].dist = m[15] - m[12];
2888 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2889 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2890 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2891 r_refdef.view.frustum[1].dist = m[15] + m[12];
2893 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2894 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2895 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2896 r_refdef.view.frustum[2].dist = m[15] - m[13];
2898 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2899 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2900 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2901 r_refdef.view.frustum[3].dist = m[15] + m[13];
2903 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2904 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2905 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2906 r_refdef.view.frustum[4].dist = m[15] - m[14];
2908 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2909 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2910 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2911 r_refdef.view.frustum[5].dist = m[15] + m[14];
2914 if (r_refdef.view.useperspective)
2916 slopex = 1.0 / r_refdef.view.frustum_x;
2917 slopey = 1.0 / r_refdef.view.frustum_y;
2918 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2919 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2920 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2921 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2922 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2924 // Leaving those out was a mistake, those were in the old code, and they
2925 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2926 // I couldn't reproduce it after adding those normalizations. --blub
2927 VectorNormalize(r_refdef.view.frustum[0].normal);
2928 VectorNormalize(r_refdef.view.frustum[1].normal);
2929 VectorNormalize(r_refdef.view.frustum[2].normal);
2930 VectorNormalize(r_refdef.view.frustum[3].normal);
2932 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2933 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2934 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2935 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2936 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2938 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2939 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2940 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2941 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2942 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2946 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2947 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2948 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2949 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2950 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2951 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2952 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2953 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2954 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2955 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2957 r_refdef.view.numfrustumplanes = 5;
2959 if (r_refdef.view.useclipplane)
2961 r_refdef.view.numfrustumplanes = 6;
2962 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2965 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2966 PlaneClassify(r_refdef.view.frustum + i);
2968 // LordHavoc: note to all quake engine coders, Quake had a special case
2969 // for 90 degrees which assumed a square view (wrong), so I removed it,
2970 // Quake2 has it disabled as well.
2972 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2973 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2974 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2975 //PlaneClassify(&frustum[0]);
2977 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2978 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2979 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2980 //PlaneClassify(&frustum[1]);
2982 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2983 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2984 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2985 //PlaneClassify(&frustum[2]);
2987 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2988 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2989 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2990 //PlaneClassify(&frustum[3]);
2993 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2994 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2995 //PlaneClassify(&frustum[4]);
2998 void R_View_Update(void)
3000 R_View_SetFrustum();
3001 R_View_WorldVisibility(r_refdef.view.useclipplane);
3002 R_View_UpdateEntityVisible();
3003 R_View_UpdateEntityLighting();
3006 void R_SetupView(qboolean allowwaterclippingplane)
3008 if (!r_refdef.view.useperspective)
3009 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);
3010 else if (gl_stencil && r_useinfinitefarclip.integer)
3011 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3013 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3015 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3017 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3019 // LordHavoc: couldn't figure out how to make this approach the
3020 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3021 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3022 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3023 dist = r_refdef.view.clipplane.dist;
3024 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3028 void R_ResetViewRendering2D(void)
3032 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3033 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3034 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3035 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3036 GL_Color(1, 1, 1, 1);
3037 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3038 GL_BlendFunc(GL_ONE, GL_ZERO);
3039 GL_AlphaTest(false);
3040 GL_ScissorTest(false);
3041 GL_DepthMask(false);
3042 GL_DepthRange(0, 1);
3043 GL_DepthTest(false);
3044 R_Mesh_Matrix(&identitymatrix);
3045 R_Mesh_ResetTextureState();
3046 GL_PolygonOffset(0, 0);
3047 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3048 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3049 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3050 qglStencilMask(~0);CHECKGLERROR
3051 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3052 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3053 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3054 R_SetupGenericShader(true);
3057 void R_ResetViewRendering3D(void)
3061 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3062 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3064 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3065 GL_Color(1, 1, 1, 1);
3066 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3067 GL_BlendFunc(GL_ONE, GL_ZERO);
3068 GL_AlphaTest(false);
3069 GL_ScissorTest(true);
3071 GL_DepthRange(0, 1);
3073 R_Mesh_Matrix(&identitymatrix);
3074 R_Mesh_ResetTextureState();
3075 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3076 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3077 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3078 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3079 qglStencilMask(~0);CHECKGLERROR
3080 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3081 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3082 GL_CullFace(r_refdef.view.cullface_back);
3083 R_SetupGenericShader(true);
3086 void R_RenderScene(void);
3087 void R_RenderWaterPlanes(void);
3089 static void R_Water_StartFrame(void)
3092 int waterwidth, waterheight, texturewidth, textureheight;
3093 r_waterstate_waterplane_t *p;
3095 // set waterwidth and waterheight to the water resolution that will be
3096 // used (often less than the screen resolution for faster rendering)
3097 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3098 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3100 // calculate desired texture sizes
3101 // can't use water if the card does not support the texture size
3102 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3103 texturewidth = textureheight = waterwidth = waterheight = 0;
3104 else if (gl_support_arb_texture_non_power_of_two)
3106 texturewidth = waterwidth;
3107 textureheight = waterheight;
3111 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3112 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3115 // allocate textures as needed
3116 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3118 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3119 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3121 if (p->texture_refraction)
3122 R_FreeTexture(p->texture_refraction);
3123 p->texture_refraction = NULL;
3124 if (p->texture_reflection)
3125 R_FreeTexture(p->texture_reflection);
3126 p->texture_reflection = NULL;
3128 memset(&r_waterstate, 0, sizeof(r_waterstate));
3129 r_waterstate.waterwidth = waterwidth;
3130 r_waterstate.waterheight = waterheight;
3131 r_waterstate.texturewidth = texturewidth;
3132 r_waterstate.textureheight = textureheight;
3135 if (r_waterstate.waterwidth)
3137 r_waterstate.enabled = true;
3139 // set up variables that will be used in shader setup
3140 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3141 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3142 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3143 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3146 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3147 r_waterstate.numwaterplanes = 0;
3150 void R_Water_AddWaterPlane(msurface_t *surface)
3152 int triangleindex, planeindex;
3158 r_waterstate_waterplane_t *p;
3159 texture_t *t = R_GetCurrentTexture(surface->texture);
3160 // just use the first triangle with a valid normal for any decisions
3161 VectorClear(normal);
3162 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3164 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3165 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3166 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3167 TriangleNormal(vert[0], vert[1], vert[2], normal);
3168 if (VectorLength2(normal) >= 0.001)
3172 VectorCopy(normal, plane.normal);
3173 VectorNormalize(plane.normal);
3174 plane.dist = DotProduct(vert[0], plane.normal);
3175 PlaneClassify(&plane);
3176 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3178 // skip backfaces (except if nocullface is set)
3179 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3181 VectorNegate(plane.normal, plane.normal);
3183 PlaneClassify(&plane);
3187 // find a matching plane if there is one
3188 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3189 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3191 if (planeindex >= r_waterstate.maxwaterplanes)
3192 return; // nothing we can do, out of planes
3194 // if this triangle does not fit any known plane rendered this frame, add one
3195 if (planeindex >= r_waterstate.numwaterplanes)
3197 // store the new plane
3198 r_waterstate.numwaterplanes++;
3200 // clear materialflags and pvs
3201 p->materialflags = 0;
3202 p->pvsvalid = false;
3204 // merge this surface's materialflags into the waterplane
3205 p->materialflags |= t->currentmaterialflags;
3206 // merge this surface's PVS into the waterplane
3207 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3208 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3209 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3211 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3216 static void R_Water_ProcessPlanes(void)
3218 r_refdef_view_t originalview;
3219 r_refdef_view_t myview;
3221 r_waterstate_waterplane_t *p;
3223 originalview = r_refdef.view;
3225 // make sure enough textures are allocated
3226 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3228 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3230 if (!p->texture_refraction)
3231 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);
3232 if (!p->texture_refraction)
3236 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3238 if (!p->texture_reflection)
3239 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);
3240 if (!p->texture_reflection)
3246 r_refdef.view = originalview;
3247 r_refdef.view.showdebug = false;
3248 r_refdef.view.width = r_waterstate.waterwidth;
3249 r_refdef.view.height = r_waterstate.waterheight;
3250 r_refdef.view.useclipplane = true;
3251 myview = r_refdef.view;
3252 r_waterstate.renderingscene = true;
3253 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3255 // render the normal view scene and copy into texture
3256 // (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)
3257 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3259 r_refdef.view = myview;
3260 r_refdef.view.clipplane = p->plane;
3261 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3262 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3263 PlaneClassify(&r_refdef.view.clipplane);
3265 R_ResetViewRendering3D();
3266 R_ClearScreen(r_refdef.fogenabled);
3270 // copy view into the screen texture
3271 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3272 GL_ActiveTexture(0);
3274 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
3277 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3279 r_refdef.view = myview;
3280 // render reflected scene and copy into texture
3281 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3282 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3283 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3284 r_refdef.view.clipplane = p->plane;
3285 // reverse the cullface settings for this render
3286 r_refdef.view.cullface_front = GL_FRONT;
3287 r_refdef.view.cullface_back = GL_BACK;
3288 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3290 r_refdef.view.usecustompvs = true;
3292 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3294 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3297 R_ResetViewRendering3D();
3298 R_ClearScreen(r_refdef.fogenabled);
3302 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3303 GL_ActiveTexture(0);
3305 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
3308 r_waterstate.renderingscene = false;
3309 r_refdef.view = originalview;
3310 R_ResetViewRendering3D();
3311 R_ClearScreen(r_refdef.fogenabled);
3315 r_refdef.view = originalview;
3316 r_waterstate.renderingscene = false;
3317 Cvar_SetValueQuick(&r_water, 0);
3318 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3322 void R_Bloom_StartFrame(void)
3324 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3326 // set bloomwidth and bloomheight to the bloom resolution that will be
3327 // used (often less than the screen resolution for faster rendering)
3328 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3329 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3330 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3331 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3332 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3334 // calculate desired texture sizes
3335 if (gl_support_arb_texture_non_power_of_two)
3337 screentexturewidth = r_refdef.view.width;
3338 screentextureheight = r_refdef.view.height;
3339 bloomtexturewidth = r_bloomstate.bloomwidth;
3340 bloomtextureheight = r_bloomstate.bloomheight;
3344 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3345 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3346 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3347 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3350 if ((r_hdr.integer || r_bloom.integer || r_motionblur.value) && ((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))
3352 Cvar_SetValueQuick(&r_hdr, 0);
3353 Cvar_SetValueQuick(&r_bloom, 0);
3354 //Cvar_SetValueQuick(&r_motionblur, 0);
3357 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && !r_motionblur.value)
3358 screentexturewidth = screentextureheight = 0;
3359 if (!r_hdr.integer && !r_bloom.integer)
3360 bloomtexturewidth = bloomtextureheight = 0;
3362 // allocate textures as needed
3363 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3365 if (r_bloomstate.texture_screen)
3366 R_FreeTexture(r_bloomstate.texture_screen);
3367 r_bloomstate.texture_screen = NULL;
3368 r_bloomstate.screentexturewidth = screentexturewidth;
3369 r_bloomstate.screentextureheight = screentextureheight;
3370 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3371 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);
3373 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3375 if (r_bloomstate.texture_bloom)
3376 R_FreeTexture(r_bloomstate.texture_bloom);
3377 r_bloomstate.texture_bloom = NULL;
3378 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3379 r_bloomstate.bloomtextureheight = bloomtextureheight;
3380 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3381 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);
3384 // set up a texcoord array for the full resolution screen image
3385 // (we have to keep this around to copy back during final render)
3386 r_bloomstate.screentexcoord2f[0] = 0;
3387 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3388 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3389 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3390 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3391 r_bloomstate.screentexcoord2f[5] = 0;
3392 r_bloomstate.screentexcoord2f[6] = 0;
3393 r_bloomstate.screentexcoord2f[7] = 0;
3395 // set up a texcoord array for the reduced resolution bloom image
3396 // (which will be additive blended over the screen image)
3397 r_bloomstate.bloomtexcoord2f[0] = 0;
3398 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3399 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3400 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3401 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3402 r_bloomstate.bloomtexcoord2f[5] = 0;
3403 r_bloomstate.bloomtexcoord2f[6] = 0;
3404 r_bloomstate.bloomtexcoord2f[7] = 0;
3406 if (r_hdr.integer || r_bloom.integer)
3408 r_bloomstate.enabled = true;
3409 r_bloomstate.hdr = r_hdr.integer != 0;
3413 void R_Bloom_CopyBloomTexture(float colorscale)
3415 r_refdef.stats.bloom++;
3417 // scale down screen texture to the bloom texture size
3419 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3420 GL_BlendFunc(GL_ONE, GL_ZERO);
3421 GL_Color(colorscale, colorscale, colorscale, 1);
3422 // TODO: optimize with multitexture or GLSL
3423 R_SetupGenericShader(true);
3424 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3425 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3426 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3427 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3429 // we now have a bloom image in the framebuffer
3430 // copy it into the bloom image texture for later processing
3431 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3432 GL_ActiveTexture(0);
3434 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
3435 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3438 void R_Bloom_CopyHDRTexture(void)
3440 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3441 GL_ActiveTexture(0);
3443 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
3444 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3447 void R_Bloom_MakeTexture(void)
3450 float xoffset, yoffset, r, brighten;
3452 r_refdef.stats.bloom++;
3454 R_ResetViewRendering2D();
3455 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3456 R_Mesh_ColorPointer(NULL, 0, 0);
3457 R_SetupGenericShader(true);
3459 // we have a bloom image in the framebuffer
3461 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3463 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3466 r = bound(0, r_bloom_colorexponent.value / x, 1);
3467 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3468 GL_Color(r, r, r, 1);
3469 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3470 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3471 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3472 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3474 // copy the vertically blurred bloom view to a texture
3475 GL_ActiveTexture(0);
3477 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
3478 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3481 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3482 brighten = r_bloom_brighten.value;
3484 brighten *= r_hdr_range.value;
3485 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3486 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3488 for (dir = 0;dir < 2;dir++)
3490 // blend on at multiple vertical offsets to achieve a vertical blur
3491 // TODO: do offset blends using GLSL
3492 GL_BlendFunc(GL_ONE, GL_ZERO);
3493 for (x = -range;x <= range;x++)
3495 if (!dir){xoffset = 0;yoffset = x;}
3496 else {xoffset = x;yoffset = 0;}
3497 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3498 yoffset /= (float)r_bloomstate.bloomtextureheight;
3499 // compute a texcoord array with the specified x and y offset
3500 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3501 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3502 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3503 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3504 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3505 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3506 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3507 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3508 // this r value looks like a 'dot' particle, fading sharply to
3509 // black at the edges
3510 // (probably not realistic but looks good enough)
3511 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3512 //r = (dir ? 1.0f : brighten)/(range*2+1);
3513 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3514 GL_Color(r, r, r, 1);
3515 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3516 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3517 GL_BlendFunc(GL_ONE, GL_ONE);
3520 // copy the vertically blurred bloom view to a texture
3521 GL_ActiveTexture(0);
3523 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
3524 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3527 // apply subtract last
3528 // (just like it would be in a GLSL shader)
3529 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3531 GL_BlendFunc(GL_ONE, GL_ZERO);
3532 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3533 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3534 GL_Color(1, 1, 1, 1);
3535 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3536 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3538 GL_BlendFunc(GL_ONE, GL_ONE);
3539 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3540 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3541 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3542 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3543 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3544 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3545 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3547 // copy the darkened bloom view to a texture
3548 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3549 GL_ActiveTexture(0);
3551 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
3552 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3556 void R_HDR_RenderBloomTexture(void)
3558 int oldwidth, oldheight;
3559 float oldcolorscale;
3561 oldcolorscale = r_refdef.view.colorscale;
3562 oldwidth = r_refdef.view.width;
3563 oldheight = r_refdef.view.height;
3564 r_refdef.view.width = r_bloomstate.bloomwidth;
3565 r_refdef.view.height = r_bloomstate.bloomheight;
3567 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3568 // TODO: add exposure compensation features
3569 // TODO: add fp16 framebuffer support
3571 r_refdef.view.showdebug = false;
3572 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3574 R_ResetViewRendering3D();
3576 R_ClearScreen(r_refdef.fogenabled);
3577 if (r_timereport_active)
3578 R_TimeReport("HDRclear");
3581 if (r_timereport_active)
3582 R_TimeReport("visibility");
3584 r_waterstate.numwaterplanes = 0;
3585 if (r_waterstate.enabled)
3586 R_RenderWaterPlanes();
3588 r_refdef.view.showdebug = true;
3590 r_waterstate.numwaterplanes = 0;
3592 R_ResetViewRendering2D();
3594 R_Bloom_CopyHDRTexture();
3595 R_Bloom_MakeTexture();
3597 // restore the view settings
3598 r_refdef.view.width = oldwidth;
3599 r_refdef.view.height = oldheight;
3600 r_refdef.view.colorscale = oldcolorscale;
3602 R_ResetViewRendering3D();
3604 R_ClearScreen(r_refdef.fogenabled);
3605 if (r_timereport_active)
3606 R_TimeReport("viewclear");
3609 static void R_BlendView(void)
3611 if (r_bloomstate.texture_screen)
3613 // make sure the buffer is available
3614 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3616 R_ResetViewRendering2D();
3617 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3618 R_Mesh_ColorPointer(NULL, 0, 0);
3619 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3620 GL_ActiveTexture(0);CHECKGLERROR
3622 if(r_motionblur.value > 0 || r_damageblur.value > 0)
3624 // declare alpha variable
3627 static float avgspeed;
3629 speed = VectorLength(cl.movement_velocity);
3631 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vtime.value), 1);
3632 avgspeed = avgspeed * (1 - a) + speed * a;
3634 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3635 speed = bound(0, speed, 1);
3636 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3638 // calculate values into a standard alpha
3641 (r_motionblur.value * speed / 80)
3643 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3646 max(0.0001, cl.time - cl.oldtime) // fps independent
3649 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3650 a = bound(0, a, r_motionblur_maxblur.value);
3652 // developer debug of current value
3653 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3658 R_SetupGenericShader(true);
3659 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3660 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3661 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3662 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3663 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3664 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3668 // copy view into the screen texture
3669 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
3670 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3673 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3675 unsigned int permutation =
3676 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3677 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3678 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3679 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3680 | (r_glsl_saturation.value != 1 ? SHADERPERMUTATION_SATURATION : 0);
3682 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3684 // render simple bloom effect
3685 // copy the screen and shrink it and darken it for the bloom process
3686 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3687 // make the bloom texture
3688 R_Bloom_MakeTexture();
3691 R_ResetViewRendering2D();
3692 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3693 R_Mesh_ColorPointer(NULL, 0, 0);
3694 GL_Color(1, 1, 1, 1);
3695 GL_BlendFunc(GL_ONE, GL_ZERO);
3696 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3697 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3698 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3699 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3700 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3701 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3702 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3703 if (r_glsl_permutation->loc_TintColor >= 0)
3704 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3705 if (r_glsl_permutation->loc_ClientTime >= 0)
3706 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3707 if (r_glsl_permutation->loc_PixelSize >= 0)
3708 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3709 if (r_glsl_permutation->loc_UserVec1 >= 0)
3711 float a=0, b=0, c=0, d=0;
3712 #if _MSC_VER >= 1400
3713 #define sscanf sscanf_s
3715 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3716 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3718 if (r_glsl_permutation->loc_UserVec2 >= 0)
3720 float a=0, b=0, c=0, d=0;
3721 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3722 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3724 if (r_glsl_permutation->loc_UserVec3 >= 0)
3726 float a=0, b=0, c=0, d=0;
3727 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3728 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3730 if (r_glsl_permutation->loc_UserVec4 >= 0)
3732 float a=0, b=0, c=0, d=0;
3733 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3734 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3736 if (r_glsl_permutation->loc_Saturation >= 0)
3737 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3738 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3739 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3745 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3747 // render high dynamic range bloom effect
3748 // the bloom texture was made earlier this render, so we just need to
3749 // blend it onto the screen...
3750 R_ResetViewRendering2D();
3751 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3752 R_Mesh_ColorPointer(NULL, 0, 0);
3753 R_SetupGenericShader(true);
3754 GL_Color(1, 1, 1, 1);
3755 GL_BlendFunc(GL_ONE, GL_ONE);
3756 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3757 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3758 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3759 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3761 else if (r_bloomstate.texture_bloom)
3763 // render simple bloom effect
3764 // copy the screen and shrink it and darken it for the bloom process
3765 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3766 // make the bloom texture
3767 R_Bloom_MakeTexture();
3768 // put the original screen image back in place and blend the bloom
3770 R_ResetViewRendering2D();
3771 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3772 R_Mesh_ColorPointer(NULL, 0, 0);
3773 GL_Color(1, 1, 1, 1);
3774 GL_BlendFunc(GL_ONE, GL_ZERO);
3775 // do both in one pass if possible
3776 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3777 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3778 if (r_textureunits.integer >= 2 && gl_combine.integer)
3780 R_SetupGenericTwoTextureShader(GL_ADD);
3781 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3782 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3786 R_SetupGenericShader(true);
3787 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3788 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3789 // now blend on the bloom texture
3790 GL_BlendFunc(GL_ONE, GL_ONE);
3791 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3792 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3794 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3795 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3797 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3799 // apply a color tint to the whole view
3800 R_ResetViewRendering2D();
3801 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3802 R_Mesh_ColorPointer(NULL, 0, 0);
3803 R_SetupGenericShader(false);
3804 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3805 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3806 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3810 matrix4x4_t r_waterscrollmatrix;
3812 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3814 if (r_refdef.fog_density)
3816 r_refdef.fogcolor[0] = r_refdef.fog_red;
3817 r_refdef.fogcolor[1] = r_refdef.fog_green;
3818 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3822 VectorCopy(r_refdef.fogcolor, fogvec);
3823 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3825 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3826 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3827 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3828 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3830 // color.rgb *= ContrastBoost * SceneBrightness;
3831 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3832 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3833 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3834 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3839 void R_UpdateVariables(void)
3843 r_refdef.scene.ambient = r_ambient.value;
3845 r_refdef.farclip = 4096;
3846 if (r_refdef.scene.worldmodel)
3847 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3848 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3850 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3851 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3852 r_refdef.polygonfactor = 0;
3853 r_refdef.polygonoffset = 0;
3854 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3855 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3857 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3858 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3859 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3860 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3861 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3862 if (r_showsurfaces.integer)
3864 r_refdef.scene.rtworld = false;
3865 r_refdef.scene.rtworldshadows = false;
3866 r_refdef.scene.rtdlight = false;
3867 r_refdef.scene.rtdlightshadows = false;
3868 r_refdef.lightmapintensity = 0;
3871 if (gamemode == GAME_NEHAHRA)
3873 if (gl_fogenable.integer)
3875 r_refdef.oldgl_fogenable = true;
3876 r_refdef.fog_density = gl_fogdensity.value;
3877 r_refdef.fog_red = gl_fogred.value;
3878 r_refdef.fog_green = gl_foggreen.value;
3879 r_refdef.fog_blue = gl_fogblue.value;
3880 r_refdef.fog_alpha = 1;
3881 r_refdef.fog_start = 0;
3882 r_refdef.fog_end = gl_skyclip.value;
3884 else if (r_refdef.oldgl_fogenable)
3886 r_refdef.oldgl_fogenable = false;
3887 r_refdef.fog_density = 0;
3888 r_refdef.fog_red = 0;
3889 r_refdef.fog_green = 0;
3890 r_refdef.fog_blue = 0;
3891 r_refdef.fog_alpha = 0;
3892 r_refdef.fog_start = 0;
3893 r_refdef.fog_end = 0;
3897 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3898 r_refdef.fog_start = max(0, r_refdef.fog_start);
3899 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3901 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3903 if (r_refdef.fog_density && r_drawfog.integer)
3905 r_refdef.fogenabled = true;
3906 // this is the point where the fog reaches 0.9986 alpha, which we
3907 // consider a good enough cutoff point for the texture
3908 // (0.9986 * 256 == 255.6)
3909 if (r_fog_exp2.integer)
3910 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3912 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3913 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3914 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3915 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3916 // fog color was already set
3917 // update the fog texture
3918 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)
3919 R_BuildFogTexture();
3922 r_refdef.fogenabled = false;
3924 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3926 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3928 // build GLSL gamma texture
3929 #define RAMPWIDTH 256
3930 unsigned short ramp[RAMPWIDTH * 3];
3931 unsigned char rampbgr[RAMPWIDTH][4];
3934 r_texture_gammaramps_serial = vid_gammatables_serial;
3936 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3937 for(i = 0; i < RAMPWIDTH; ++i)
3939 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3940 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3941 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3944 if (r_texture_gammaramps)
3946 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3950 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);
3956 // remove GLSL gamma texture
3960 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3961 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3967 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3968 if( scenetype != r_currentscenetype ) {
3969 // store the old scenetype
3970 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3971 r_currentscenetype = scenetype;
3972 // move in the new scene
3973 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3982 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3984 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3985 if( scenetype == r_currentscenetype ) {
3986 return &r_refdef.scene;
3988 return &r_scenes_store[ scenetype ];
3997 void R_RenderView(void)
3999 r_frame++; // used only by R_GetCurrentTexture
4000 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4002 if (r_refdef.view.isoverlay)
4004 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4005 GL_Clear( GL_DEPTH_BUFFER_BIT );
4006 R_TimeReport("depthclear");
4008 r_refdef.view.showdebug = false;
4010 r_waterstate.enabled = false;
4011 r_waterstate.numwaterplanes = 0;
4019 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4020 return; //Host_Error ("R_RenderView: NULL worldmodel");
4022 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4024 // break apart the view matrix into vectors for various purposes
4025 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4026 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4027 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4028 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4029 // make an inverted copy of the view matrix for tracking sprites
4030 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4032 R_Shadow_UpdateWorldLightSelection();
4034 R_Bloom_StartFrame();
4035 R_Water_StartFrame();
4038 if (r_timereport_active)
4039 R_TimeReport("viewsetup");
4041 R_ResetViewRendering3D();
4043 if (r_refdef.view.clear || r_refdef.fogenabled)
4045 R_ClearScreen(r_refdef.fogenabled);
4046 if (r_timereport_active)
4047 R_TimeReport("viewclear");
4049 r_refdef.view.clear = true;
4051 // this produces a bloom texture to be used in R_BlendView() later
4053 R_HDR_RenderBloomTexture();
4055 r_refdef.view.showdebug = true;
4058 if (r_timereport_active)
4059 R_TimeReport("visibility");
4061 r_waterstate.numwaterplanes = 0;
4062 if (r_waterstate.enabled)
4063 R_RenderWaterPlanes();
4066 r_waterstate.numwaterplanes = 0;
4069 if (r_timereport_active)
4070 R_TimeReport("blendview");
4072 GL_Scissor(0, 0, vid.width, vid.height);
4073 GL_ScissorTest(false);
4077 void R_RenderWaterPlanes(void)
4079 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4081 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4082 if (r_timereport_active)
4083 R_TimeReport("waterworld");
4086 // don't let sound skip if going slow
4087 if (r_refdef.scene.extraupdate)
4090 R_DrawModelsAddWaterPlanes();
4091 if (r_timereport_active)
4092 R_TimeReport("watermodels");
4094 if (r_waterstate.numwaterplanes)
4096 R_Water_ProcessPlanes();
4097 if (r_timereport_active)
4098 R_TimeReport("waterscenes");
4102 extern void R_DrawLightningBeams (void);
4103 extern void VM_CL_AddPolygonsToMeshQueue (void);
4104 extern void R_DrawPortals (void);
4105 extern cvar_t cl_locs_show;
4106 static void R_DrawLocs(void);
4107 static void R_DrawEntityBBoxes(void);
4108 void R_RenderScene(void)
4110 r_refdef.stats.renders++;
4114 // don't let sound skip if going slow
4115 if (r_refdef.scene.extraupdate)
4118 R_MeshQueue_BeginScene();
4122 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);
4124 if (cl.csqc_vidvars.drawworld)
4126 // don't let sound skip if going slow
4127 if (r_refdef.scene.extraupdate)
4130 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4132 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4133 if (r_timereport_active)
4134 R_TimeReport("worldsky");
4137 if (R_DrawBrushModelsSky() && r_timereport_active)
4138 R_TimeReport("bmodelsky");
4141 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4143 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4144 if (r_timereport_active)
4145 R_TimeReport("worlddepth");
4147 if (r_depthfirst.integer >= 2)
4149 R_DrawModelsDepth();
4150 if (r_timereport_active)
4151 R_TimeReport("modeldepth");
4154 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4156 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4157 if (r_timereport_active)
4158 R_TimeReport("world");
4161 // don't let sound skip if going slow
4162 if (r_refdef.scene.extraupdate)
4166 if (r_timereport_active)
4167 R_TimeReport("models");
4169 // don't let sound skip if going slow
4170 if (r_refdef.scene.extraupdate)
4173 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4175 R_DrawModelShadows();
4177 R_ResetViewRendering3D();
4179 // don't let sound skip if going slow
4180 if (r_refdef.scene.extraupdate)
4184 R_ShadowVolumeLighting(false);
4185 if (r_timereport_active)
4186 R_TimeReport("rtlights");
4188 // don't let sound skip if going slow
4189 if (r_refdef.scene.extraupdate)
4192 if (cl.csqc_vidvars.drawworld)
4194 R_DrawLightningBeams();
4195 if (r_timereport_active)
4196 R_TimeReport("lightning");
4199 if (r_timereport_active)
4200 R_TimeReport("decals");
4203 if (r_timereport_active)
4204 R_TimeReport("particles");
4207 if (r_timereport_active)
4208 R_TimeReport("explosions");
4211 R_SetupGenericShader(true);
4212 VM_CL_AddPolygonsToMeshQueue();
4214 if (r_refdef.view.showdebug)
4216 if (cl_locs_show.integer)
4219 if (r_timereport_active)
4220 R_TimeReport("showlocs");
4223 if (r_drawportals.integer)
4226 if (r_timereport_active)
4227 R_TimeReport("portals");
4230 if (r_showbboxes.value > 0)
4232 R_DrawEntityBBoxes();
4233 if (r_timereport_active)
4234 R_TimeReport("bboxes");
4238 R_SetupGenericShader(true);
4239 R_MeshQueue_RenderTransparent();
4240 if (r_timereport_active)
4241 R_TimeReport("drawtrans");
4243 R_SetupGenericShader(true);
4245 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))
4247 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4248 if (r_timereport_active)
4249 R_TimeReport("worlddebug");
4250 R_DrawModelsDebug();
4251 if (r_timereport_active)
4252 R_TimeReport("modeldebug");
4255 R_SetupGenericShader(true);
4257 if (cl.csqc_vidvars.drawworld)
4260 if (r_timereport_active)
4261 R_TimeReport("coronas");
4264 // don't let sound skip if going slow
4265 if (r_refdef.scene.extraupdate)
4268 R_ResetViewRendering2D();
4271 static const unsigned short bboxelements[36] =
4281 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4284 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4285 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4286 GL_DepthMask(false);
4287 GL_DepthRange(0, 1);
4288 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4289 R_Mesh_Matrix(&identitymatrix);
4290 R_Mesh_ResetTextureState();
4292 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4293 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4294 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4295 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4296 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4297 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4298 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4299 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4300 R_FillColors(color4f, 8, cr, cg, cb, ca);
4301 if (r_refdef.fogenabled)
4303 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4305 f1 = FogPoint_World(v);
4307 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4308 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4309 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4312 R_Mesh_VertexPointer(vertex3f, 0, 0);
4313 R_Mesh_ColorPointer(color4f, 0, 0);
4314 R_Mesh_ResetTextureState();
4315 R_SetupGenericShader(false);
4316 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4319 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4323 prvm_edict_t *edict;
4324 prvm_prog_t *prog_save = prog;
4326 // this function draws bounding boxes of server entities
4330 GL_CullFace(GL_NONE);
4331 R_SetupGenericShader(false);
4335 for (i = 0;i < numsurfaces;i++)
4337 edict = PRVM_EDICT_NUM(surfacelist[i]);
4338 switch ((int)edict->fields.server->solid)
4340 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4341 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4342 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4343 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4344 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4345 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4347 color[3] *= r_showbboxes.value;
4348 color[3] = bound(0, color[3], 1);
4349 GL_DepthTest(!r_showdisabledepthtest.integer);
4350 GL_CullFace(r_refdef.view.cullface_front);
4351 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4357 static void R_DrawEntityBBoxes(void)
4360 prvm_edict_t *edict;
4362 prvm_prog_t *prog_save = prog;
4364 // this function draws bounding boxes of server entities
4370 for (i = 0;i < prog->num_edicts;i++)
4372 edict = PRVM_EDICT_NUM(i);
4373 if (edict->priv.server->free)
4375 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4376 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4378 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4380 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4381 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4387 unsigned short nomodelelements[24] =
4399 float nomodelvertex3f[6*3] =
4409 float nomodelcolor4f[6*4] =
4411 0.0f, 0.0f, 0.5f, 1.0f,
4412 0.0f, 0.0f, 0.5f, 1.0f,
4413 0.0f, 0.5f, 0.0f, 1.0f,
4414 0.0f, 0.5f, 0.0f, 1.0f,
4415 0.5f, 0.0f, 0.0f, 1.0f,
4416 0.5f, 0.0f, 0.0f, 1.0f
4419 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4424 // this is only called once per entity so numsurfaces is always 1, and
4425 // surfacelist is always {0}, so this code does not handle batches
4426 R_Mesh_Matrix(&ent->matrix);
4428 if (ent->flags & EF_ADDITIVE)
4430 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4431 GL_DepthMask(false);
4433 else if (ent->alpha < 1)
4435 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4436 GL_DepthMask(false);
4440 GL_BlendFunc(GL_ONE, GL_ZERO);
4443 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4444 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4445 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4446 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4447 R_SetupGenericShader(false);
4448 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4449 if (r_refdef.fogenabled)
4452 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4453 R_Mesh_ColorPointer(color4f, 0, 0);
4454 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4455 f1 = FogPoint_World(org);
4457 for (i = 0, c = color4f;i < 6;i++, c += 4)
4459 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4460 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4461 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4465 else if (ent->alpha != 1)
4467 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4468 R_Mesh_ColorPointer(color4f, 0, 0);
4469 for (i = 0, c = color4f;i < 6;i++, c += 4)
4473 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4474 R_Mesh_ResetTextureState();
4475 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4478 void R_DrawNoModel(entity_render_t *ent)
4481 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4482 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4483 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4485 // R_DrawNoModelCallback(ent, 0);
4488 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4490 vec3_t right1, right2, diff, normal;
4492 VectorSubtract (org2, org1, normal);
4494 // calculate 'right' vector for start
4495 VectorSubtract (r_refdef.view.origin, org1, diff);
4496 CrossProduct (normal, diff, right1);
4497 VectorNormalize (right1);
4499 // calculate 'right' vector for end
4500 VectorSubtract (r_refdef.view.origin, org2, diff);
4501 CrossProduct (normal, diff, right2);
4502 VectorNormalize (right2);
4504 vert[ 0] = org1[0] + width * right1[0];
4505 vert[ 1] = org1[1] + width * right1[1];
4506 vert[ 2] = org1[2] + width * right1[2];
4507 vert[ 3] = org1[0] - width * right1[0];
4508 vert[ 4] = org1[1] - width * right1[1];
4509 vert[ 5] = org1[2] - width * right1[2];
4510 vert[ 6] = org2[0] - width * right2[0];
4511 vert[ 7] = org2[1] - width * right2[1];
4512 vert[ 8] = org2[2] - width * right2[2];
4513 vert[ 9] = org2[0] + width * right2[0];
4514 vert[10] = org2[1] + width * right2[1];
4515 vert[11] = org2[2] + width * right2[2];
4518 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4520 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)
4522 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4526 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4527 fog = FogPoint_World(origin);
4529 R_Mesh_Matrix(&identitymatrix);
4530 GL_BlendFunc(blendfunc1, blendfunc2);
4532 GL_CullFace(GL_NONE);
4534 GL_DepthMask(false);
4535 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4536 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4537 GL_DepthTest(!depthdisable);
4539 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4540 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4541 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4542 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4543 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4544 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4545 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4546 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4547 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4548 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4549 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4550 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4552 R_Mesh_VertexPointer(vertex3f, 0, 0);
4553 R_Mesh_ColorPointer(NULL, 0, 0);
4554 R_Mesh_ResetTextureState();
4555 R_SetupGenericShader(true);
4556 R_Mesh_TexBind(0, R_GetTexture(texture));
4557 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4558 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4559 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4560 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4562 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4564 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4565 GL_BlendFunc(blendfunc1, GL_ONE);
4567 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4568 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4572 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4577 VectorSet(v, x, y, z);
4578 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4579 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4581 if (i == mesh->numvertices)
4583 if (mesh->numvertices < mesh->maxvertices)
4585 VectorCopy(v, vertex3f);
4586 mesh->numvertices++;
4588 return mesh->numvertices;
4594 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4598 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4599 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4600 e = mesh->element3i + mesh->numtriangles * 3;
4601 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4603 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4604 if (mesh->numtriangles < mesh->maxtriangles)
4609 mesh->numtriangles++;
4611 element[1] = element[2];
4615 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4619 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4620 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4621 e = mesh->element3i + mesh->numtriangles * 3;
4622 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4624 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4625 if (mesh->numtriangles < mesh->maxtriangles)
4630 mesh->numtriangles++;
4632 element[1] = element[2];
4636 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4637 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4639 int planenum, planenum2;
4642 mplane_t *plane, *plane2;
4644 double temppoints[2][256*3];
4645 // figure out how large a bounding box we need to properly compute this brush
4647 for (w = 0;w < numplanes;w++)
4648 maxdist = max(maxdist, planes[w].dist);
4649 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4650 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4651 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4655 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4656 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4658 if (planenum2 == planenum)
4660 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);
4663 if (tempnumpoints < 3)
4665 // generate elements forming a triangle fan for this polygon
4666 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4670 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)
4672 texturelayer_t *layer;
4673 layer = t->currentlayers + t->currentnumlayers++;
4675 layer->depthmask = depthmask;
4676 layer->blendfunc1 = blendfunc1;
4677 layer->blendfunc2 = blendfunc2;
4678 layer->texture = texture;
4679 layer->texmatrix = *matrix;
4680 layer->color[0] = r * r_refdef.view.colorscale;
4681 layer->color[1] = g * r_refdef.view.colorscale;
4682 layer->color[2] = b * r_refdef.view.colorscale;
4683 layer->color[3] = a;
4686 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4689 index = parms[2] + r_refdef.scene.time * parms[3];
4690 index -= floor(index);
4694 case Q3WAVEFUNC_NONE:
4695 case Q3WAVEFUNC_NOISE:
4696 case Q3WAVEFUNC_COUNT:
4699 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4700 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4701 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4702 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4703 case Q3WAVEFUNC_TRIANGLE:
4705 f = index - floor(index);
4716 return (float)(parms[0] + parms[1] * f);
4719 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4724 matrix4x4_t matrix, temp;
4725 switch(tcmod->tcmod)
4729 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4730 matrix = r_waterscrollmatrix;
4732 matrix = identitymatrix;
4734 case Q3TCMOD_ENTITYTRANSLATE:
4735 // this is used in Q3 to allow the gamecode to control texcoord
4736 // scrolling on the entity, which is not supported in darkplaces yet.
4737 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4739 case Q3TCMOD_ROTATE:
4740 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4741 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4742 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4745 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4747 case Q3TCMOD_SCROLL:
4748 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4750 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4751 w = (int) tcmod->parms[0];
4752 h = (int) tcmod->parms[1];
4753 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4755 idx = (int) floor(f * w * h);
4756 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4758 case Q3TCMOD_STRETCH:
4759 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4760 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4762 case Q3TCMOD_TRANSFORM:
4763 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4764 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4765 VectorSet(tcmat + 6, 0 , 0 , 1);
4766 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4767 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4769 case Q3TCMOD_TURBULENT:
4770 // this is handled in the RSurf_PrepareVertices function
4771 matrix = identitymatrix;
4775 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4778 texture_t *R_GetCurrentTexture(texture_t *t)
4781 const entity_render_t *ent = rsurface.entity;
4782 dp_model_t *model = ent->model;
4783 q3shaderinfo_layer_tcmod_t *tcmod;
4785 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4786 return t->currentframe;
4787 t->update_lastrenderframe = r_frame;
4788 t->update_lastrenderentity = (void *)ent;
4790 // switch to an alternate material if this is a q1bsp animated material
4792 texture_t *texture = t;
4793 int s = ent->skinnum;
4794 if ((unsigned int)s >= (unsigned int)model->numskins)
4796 if (model->skinscenes)
4798 if (model->skinscenes[s].framecount > 1)
4799 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4801 s = model->skinscenes[s].firstframe;
4804 t = t + s * model->num_surfaces;
4807 // use an alternate animation if the entity's frame is not 0,
4808 // and only if the texture has an alternate animation
4809 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4810 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4812 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4814 texture->currentframe = t;
4817 // update currentskinframe to be a qw skin or animation frame
4818 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"))
4820 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4822 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4823 if (developer_loading.integer)
4824 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4825 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);
4827 t->currentskinframe = r_qwskincache_skinframe[i];
4828 if (t->currentskinframe == NULL)
4829 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4831 else if (t->numskinframes >= 2)
4832 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4833 if (t->backgroundnumskinframes >= 2)
4834 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4836 t->currentmaterialflags = t->basematerialflags;
4837 t->currentalpha = ent->alpha;
4838 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4839 t->currentalpha *= r_wateralpha.value;
4840 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4841 t->currentalpha *= t->r_water_wateralpha;
4842 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4843 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4844 if (!(ent->flags & RENDER_LIGHT))
4845 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4846 else if (rsurface.modeltexcoordlightmap2f == NULL)
4848 // pick a model lighting mode
4849 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4850 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4852 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4854 if (ent->effects & EF_ADDITIVE)
4855 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4856 else if (t->currentalpha < 1)
4857 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4858 if (ent->effects & EF_DOUBLESIDED)
4859 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4860 if (ent->effects & EF_NODEPTHTEST)
4861 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4862 if (ent->flags & RENDER_VIEWMODEL)
4863 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4864 if (t->backgroundnumskinframes)
4865 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4866 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4868 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4869 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4872 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4874 // there is no tcmod
4875 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4877 t->currenttexmatrix = r_waterscrollmatrix;
4878 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
4882 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
4883 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
4886 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4887 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
4888 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4889 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
4891 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4892 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4893 t->glosstexture = r_texture_black;
4894 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4895 t->backgroundglosstexture = r_texture_black;
4896 t->specularpower = r_shadow_glossexponent.value;
4897 // TODO: store reference values for these in the texture?
4898 t->specularscale = 0;
4899 if (r_shadow_gloss.integer > 0)
4901 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4903 if (r_shadow_glossintensity.value > 0)
4905 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4906 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4907 t->specularscale = r_shadow_glossintensity.value;
4910 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4912 t->glosstexture = r_texture_white;
4913 t->backgroundglosstexture = r_texture_white;
4914 t->specularscale = r_shadow_gloss2intensity.value;
4918 // lightmaps mode looks bad with dlights using actual texturing, so turn
4919 // off the colormap and glossmap, but leave the normalmap on as it still
4920 // accurately represents the shading involved
4921 if (gl_lightmaps.integer)
4923 t->basetexture = r_texture_grey128;
4924 t->backgroundbasetexture = NULL;
4925 t->specularscale = 0;
4926 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4929 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4930 VectorClear(t->dlightcolor);
4931 t->currentnumlayers = 0;
4932 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4935 int blendfunc1, blendfunc2, depthmask;
4936 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4938 blendfunc1 = GL_SRC_ALPHA;
4939 blendfunc2 = GL_ONE;
4941 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4943 blendfunc1 = GL_SRC_ALPHA;
4944 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4946 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4948 blendfunc1 = t->customblendfunc[0];
4949 blendfunc2 = t->customblendfunc[1];
4953 blendfunc1 = GL_ONE;
4954 blendfunc2 = GL_ZERO;
4956 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4957 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4958 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4959 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4961 // fullbright is not affected by r_refdef.lightmapintensity
4962 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]);
4963 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4964 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]);
4965 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4966 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]);
4970 vec3_t ambientcolor;
4972 // set the color tint used for lights affecting this surface
4973 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4975 // q3bsp has no lightmap updates, so the lightstylevalue that
4976 // would normally be baked into the lightmap must be
4977 // applied to the color
4978 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4979 if (ent->model->type == mod_brushq3)
4980 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4981 colorscale *= r_refdef.lightmapintensity;
4982 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4983 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4984 // basic lit geometry
4985 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]);
4986 // add pants/shirt if needed
4987 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4988 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]);
4989 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4990 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]);
4991 // now add ambient passes if needed
4992 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4994 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]);
4995 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4996 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]);
4997 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4998 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]);
5001 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5002 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]);
5003 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5005 // if this is opaque use alpha blend which will darken the earlier
5008 // if this is an alpha blended material, all the earlier passes
5009 // were darkened by fog already, so we only need to add the fog
5010 // color ontop through the fog mask texture
5012 // if this is an additive blended material, all the earlier passes
5013 // were darkened by fog already, and we should not add fog color
5014 // (because the background was not darkened, there is no fog color
5015 // that was lost behind it).
5016 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]);
5020 return t->currentframe;
5023 rsurfacestate_t rsurface;
5025 void R_Mesh_ResizeArrays(int newvertices)
5028 if (rsurface.array_size >= newvertices)
5030 if (rsurface.array_modelvertex3f)
5031 Mem_Free(rsurface.array_modelvertex3f);
5032 rsurface.array_size = (newvertices + 1023) & ~1023;
5033 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5034 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5035 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5036 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5037 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5038 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5039 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5040 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5041 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5042 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5043 rsurface.array_color4f = base + rsurface.array_size * 27;
5044 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5047 void RSurf_ActiveWorldEntity(void)
5049 dp_model_t *model = r_refdef.scene.worldmodel;
5050 //if (rsurface.entity == r_refdef.scene.worldentity)
5052 rsurface.entity = r_refdef.scene.worldentity;
5053 if (rsurface.array_size < model->surfmesh.num_vertices)
5054 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5055 rsurface.matrix = identitymatrix;
5056 rsurface.inversematrix = identitymatrix;
5057 R_Mesh_Matrix(&identitymatrix);
5058 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5059 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5060 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5061 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5062 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5063 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5064 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5065 rsurface.frameblend[0].lerp = 1;
5066 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5067 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5068 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5069 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5070 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5071 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5072 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5073 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5074 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5075 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5076 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5077 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5078 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5079 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5080 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5081 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5082 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5083 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5084 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5085 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5086 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5087 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5088 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5089 rsurface.modelelement3i = model->surfmesh.data_element3i;
5090 rsurface.modelelement3s = model->surfmesh.data_element3s;
5091 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5092 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5093 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5094 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5095 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5096 rsurface.modelsurfaces = model->data_surfaces;
5097 rsurface.generatedvertex = false;
5098 rsurface.vertex3f = rsurface.modelvertex3f;
5099 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5100 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5101 rsurface.svector3f = rsurface.modelsvector3f;
5102 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5103 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5104 rsurface.tvector3f = rsurface.modeltvector3f;
5105 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5106 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5107 rsurface.normal3f = rsurface.modelnormal3f;
5108 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5109 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5110 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5113 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5115 dp_model_t *model = ent->model;
5116 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5118 rsurface.entity = (entity_render_t *)ent;
5119 if (rsurface.array_size < model->surfmesh.num_vertices)
5120 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5121 rsurface.matrix = ent->matrix;
5122 rsurface.inversematrix = ent->inversematrix;
5123 R_Mesh_Matrix(&rsurface.matrix);
5124 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5125 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5126 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5127 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5128 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5129 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5130 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5131 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5132 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5133 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5134 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5135 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5136 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5137 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5138 if (ent->model->brush.submodel)
5140 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5141 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5143 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5147 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5148 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5149 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5150 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5151 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5153 else if (wantnormals)
5155 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5156 rsurface.modelsvector3f = NULL;
5157 rsurface.modeltvector3f = NULL;
5158 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5159 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5163 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5164 rsurface.modelsvector3f = NULL;
5165 rsurface.modeltvector3f = NULL;
5166 rsurface.modelnormal3f = NULL;
5167 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5169 rsurface.modelvertex3f_bufferobject = 0;
5170 rsurface.modelvertex3f_bufferoffset = 0;
5171 rsurface.modelsvector3f_bufferobject = 0;
5172 rsurface.modelsvector3f_bufferoffset = 0;
5173 rsurface.modeltvector3f_bufferobject = 0;
5174 rsurface.modeltvector3f_bufferoffset = 0;
5175 rsurface.modelnormal3f_bufferobject = 0;
5176 rsurface.modelnormal3f_bufferoffset = 0;
5177 rsurface.generatedvertex = true;
5181 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5182 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5183 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5184 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5185 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5186 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5187 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5188 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5189 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5190 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5191 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5192 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5193 rsurface.generatedvertex = false;
5195 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5196 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5197 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5198 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5199 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5200 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5201 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5202 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5203 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5204 rsurface.modelelement3i = model->surfmesh.data_element3i;
5205 rsurface.modelelement3s = model->surfmesh.data_element3s;
5206 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5207 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5208 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5209 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5210 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5211 rsurface.modelsurfaces = model->data_surfaces;
5212 rsurface.vertex3f = rsurface.modelvertex3f;
5213 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5214 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5215 rsurface.svector3f = rsurface.modelsvector3f;
5216 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5217 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5218 rsurface.tvector3f = rsurface.modeltvector3f;
5219 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5220 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5221 rsurface.normal3f = rsurface.modelnormal3f;
5222 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5223 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5224 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5227 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5228 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5231 int texturesurfaceindex;
5236 const float *v1, *in_tc;
5238 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5240 q3shaderinfo_deform_t *deform;
5241 // 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
5242 if (rsurface.generatedvertex)
5244 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5245 generatenormals = true;
5246 for (i = 0;i < Q3MAXDEFORMS;i++)
5248 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5250 generatetangents = true;
5251 generatenormals = true;
5253 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5254 generatenormals = true;
5256 if (generatenormals && !rsurface.modelnormal3f)
5258 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5259 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5260 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5261 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5263 if (generatetangents && !rsurface.modelsvector3f)
5265 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5266 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5267 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5268 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5269 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5270 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5271 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);
5274 rsurface.vertex3f = rsurface.modelvertex3f;
5275 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5276 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5277 rsurface.svector3f = rsurface.modelsvector3f;
5278 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5279 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5280 rsurface.tvector3f = rsurface.modeltvector3f;
5281 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5282 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5283 rsurface.normal3f = rsurface.modelnormal3f;
5284 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5285 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5286 // if vertices are deformed (sprite flares and things in maps, possibly
5287 // water waves, bulges and other deformations), generate them into
5288 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5289 // (may be static model data or generated data for an animated model, or
5290 // the previous deform pass)
5291 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5293 switch (deform->deform)
5296 case Q3DEFORM_PROJECTIONSHADOW:
5297 case Q3DEFORM_TEXT0:
5298 case Q3DEFORM_TEXT1:
5299 case Q3DEFORM_TEXT2:
5300 case Q3DEFORM_TEXT3:
5301 case Q3DEFORM_TEXT4:
5302 case Q3DEFORM_TEXT5:
5303 case Q3DEFORM_TEXT6:
5304 case Q3DEFORM_TEXT7:
5307 case Q3DEFORM_AUTOSPRITE:
5308 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5309 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5310 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5311 VectorNormalize(newforward);
5312 VectorNormalize(newright);
5313 VectorNormalize(newup);
5314 // make deformed versions of only the model vertices used by the specified surfaces
5315 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5317 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5318 // a single autosprite surface can contain multiple sprites...
5319 for (j = 0;j < surface->num_vertices - 3;j += 4)
5321 VectorClear(center);
5322 for (i = 0;i < 4;i++)
5323 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5324 VectorScale(center, 0.25f, center);
5325 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5326 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5327 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5328 for (i = 0;i < 4;i++)
5330 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5331 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5334 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);
5335 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);
5337 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5338 rsurface.vertex3f_bufferobject = 0;
5339 rsurface.vertex3f_bufferoffset = 0;
5340 rsurface.svector3f = rsurface.array_deformedsvector3f;
5341 rsurface.svector3f_bufferobject = 0;
5342 rsurface.svector3f_bufferoffset = 0;
5343 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5344 rsurface.tvector3f_bufferobject = 0;
5345 rsurface.tvector3f_bufferoffset = 0;
5346 rsurface.normal3f = rsurface.array_deformednormal3f;
5347 rsurface.normal3f_bufferobject = 0;
5348 rsurface.normal3f_bufferoffset = 0;
5350 case Q3DEFORM_AUTOSPRITE2:
5351 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5352 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5353 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5354 VectorNormalize(newforward);
5355 VectorNormalize(newright);
5356 VectorNormalize(newup);
5357 // make deformed versions of only the model vertices used by the specified surfaces
5358 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5360 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5361 const float *v1, *v2;
5371 memset(shortest, 0, sizeof(shortest));
5372 // a single autosprite surface can contain multiple sprites...
5373 for (j = 0;j < surface->num_vertices - 3;j += 4)
5375 VectorClear(center);
5376 for (i = 0;i < 4;i++)
5377 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5378 VectorScale(center, 0.25f, center);
5379 // find the two shortest edges, then use them to define the
5380 // axis vectors for rotating around the central axis
5381 for (i = 0;i < 6;i++)
5383 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5384 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5386 Debug_PolygonBegin(NULL, 0);
5387 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5388 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);
5389 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5392 l = VectorDistance2(v1, v2);
5393 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5395 l += (1.0f / 1024.0f);
5396 if (shortest[0].length2 > l || i == 0)
5398 shortest[1] = shortest[0];
5399 shortest[0].length2 = l;
5400 shortest[0].v1 = v1;
5401 shortest[0].v2 = v2;
5403 else if (shortest[1].length2 > l || i == 1)
5405 shortest[1].length2 = l;
5406 shortest[1].v1 = v1;
5407 shortest[1].v2 = v2;
5410 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5411 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5413 Debug_PolygonBegin(NULL, 0);
5414 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5415 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);
5416 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5419 // this calculates the right vector from the shortest edge
5420 // and the up vector from the edge midpoints
5421 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5422 VectorNormalize(right);
5423 VectorSubtract(end, start, up);
5424 VectorNormalize(up);
5425 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5426 //VectorSubtract(rsurface.modelorg, center, forward);
5427 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5428 VectorNegate(forward, forward);
5429 VectorReflect(forward, 0, up, forward);
5430 VectorNormalize(forward);
5431 CrossProduct(up, forward, newright);
5432 VectorNormalize(newright);
5434 Debug_PolygonBegin(NULL, 0);
5435 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);
5436 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5437 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5441 Debug_PolygonBegin(NULL, 0);
5442 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5443 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5444 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5447 // rotate the quad around the up axis vector, this is made
5448 // especially easy by the fact we know the quad is flat,
5449 // so we only have to subtract the center position and
5450 // measure distance along the right vector, and then
5451 // multiply that by the newright vector and add back the
5453 // we also need to subtract the old position to undo the
5454 // displacement from the center, which we do with a
5455 // DotProduct, the subtraction/addition of center is also
5456 // optimized into DotProducts here
5457 l = DotProduct(right, center);
5458 for (i = 0;i < 4;i++)
5460 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5461 f = DotProduct(right, v1) - l;
5462 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5465 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);
5466 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);
5468 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5469 rsurface.vertex3f_bufferobject = 0;
5470 rsurface.vertex3f_bufferoffset = 0;
5471 rsurface.svector3f = rsurface.array_deformedsvector3f;
5472 rsurface.svector3f_bufferobject = 0;
5473 rsurface.svector3f_bufferoffset = 0;
5474 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5475 rsurface.tvector3f_bufferobject = 0;
5476 rsurface.tvector3f_bufferoffset = 0;
5477 rsurface.normal3f = rsurface.array_deformednormal3f;
5478 rsurface.normal3f_bufferobject = 0;
5479 rsurface.normal3f_bufferoffset = 0;
5481 case Q3DEFORM_NORMAL:
5482 // deform the normals to make reflections wavey
5483 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5485 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5486 for (j = 0;j < surface->num_vertices;j++)
5489 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5490 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5491 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5492 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5493 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5494 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5495 VectorNormalize(normal);
5497 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);
5499 rsurface.svector3f = rsurface.array_deformedsvector3f;
5500 rsurface.svector3f_bufferobject = 0;
5501 rsurface.svector3f_bufferoffset = 0;
5502 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5503 rsurface.tvector3f_bufferobject = 0;
5504 rsurface.tvector3f_bufferoffset = 0;
5505 rsurface.normal3f = rsurface.array_deformednormal3f;
5506 rsurface.normal3f_bufferobject = 0;
5507 rsurface.normal3f_bufferoffset = 0;
5510 // deform vertex array to make wavey water and flags and such
5511 waveparms[0] = deform->waveparms[0];
5512 waveparms[1] = deform->waveparms[1];
5513 waveparms[2] = deform->waveparms[2];
5514 waveparms[3] = deform->waveparms[3];
5515 // this is how a divisor of vertex influence on deformation
5516 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5517 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5518 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5520 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5521 for (j = 0;j < surface->num_vertices;j++)
5523 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5524 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5525 // if the wavefunc depends on time, evaluate it per-vertex
5528 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5529 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5531 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5534 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5535 rsurface.vertex3f_bufferobject = 0;
5536 rsurface.vertex3f_bufferoffset = 0;
5538 case Q3DEFORM_BULGE:
5539 // deform vertex array to make the surface have moving bulges
5540 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5542 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5543 for (j = 0;j < surface->num_vertices;j++)
5545 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5546 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5549 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5550 rsurface.vertex3f_bufferobject = 0;
5551 rsurface.vertex3f_bufferoffset = 0;
5554 // deform vertex array
5555 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5556 VectorScale(deform->parms, scale, waveparms);
5557 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5559 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5560 for (j = 0;j < surface->num_vertices;j++)
5561 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5563 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5564 rsurface.vertex3f_bufferobject = 0;
5565 rsurface.vertex3f_bufferoffset = 0;
5569 // generate texcoords based on the chosen texcoord source
5570 switch(rsurface.texture->tcgen.tcgen)
5573 case Q3TCGEN_TEXTURE:
5574 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5575 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5576 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5578 case Q3TCGEN_LIGHTMAP:
5579 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5580 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5581 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5583 case Q3TCGEN_VECTOR:
5584 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5586 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5587 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)
5589 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5590 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5593 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5594 rsurface.texcoordtexture2f_bufferobject = 0;
5595 rsurface.texcoordtexture2f_bufferoffset = 0;
5597 case Q3TCGEN_ENVIRONMENT:
5598 // make environment reflections using a spheremap
5599 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5601 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5602 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5603 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5604 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5605 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5607 // identical to Q3A's method, but executed in worldspace so
5608 // carried models can be shiny too
5610 float viewer[3], d, reflected[3], worldreflected[3];
5612 VectorSubtract(rsurface.modelorg, vertex, viewer);
5613 // VectorNormalize(viewer);
5615 d = DotProduct(normal, viewer);
5617 reflected[0] = normal[0]*2*d - viewer[0];
5618 reflected[1] = normal[1]*2*d - viewer[1];
5619 reflected[2] = normal[2]*2*d - viewer[2];
5620 // note: this is proportinal to viewer, so we can normalize later
5622 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5623 VectorNormalize(worldreflected);
5625 // note: this sphere map only uses world x and z!
5626 // so positive and negative y will LOOK THE SAME.
5627 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5628 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5631 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5632 rsurface.texcoordtexture2f_bufferobject = 0;
5633 rsurface.texcoordtexture2f_bufferoffset = 0;
5636 // the only tcmod that needs software vertex processing is turbulent, so
5637 // check for it here and apply the changes if needed
5638 // and we only support that as the first one
5639 // (handling a mixture of turbulent and other tcmods would be problematic
5640 // without punting it entirely to a software path)
5641 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5643 amplitude = rsurface.texture->tcmods[0].parms[1];
5644 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5645 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5647 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5648 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)
5650 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5651 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5654 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5655 rsurface.texcoordtexture2f_bufferobject = 0;
5656 rsurface.texcoordtexture2f_bufferoffset = 0;
5658 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5659 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5660 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5661 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5664 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5667 const msurface_t *surface = texturesurfacelist[0];
5668 const msurface_t *surface2;
5673 // TODO: lock all array ranges before render, rather than on each surface
5674 if (texturenumsurfaces == 1)
5676 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5677 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);
5679 else if (r_batchmode.integer == 2)
5681 #define MAXBATCHTRIANGLES 4096
5682 int batchtriangles = 0;
5683 int batchelements[MAXBATCHTRIANGLES*3];
5684 for (i = 0;i < texturenumsurfaces;i = j)
5686 surface = texturesurfacelist[i];
5688 if (surface->num_triangles > MAXBATCHTRIANGLES)
5690 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);
5693 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5694 batchtriangles = surface->num_triangles;
5695 firstvertex = surface->num_firstvertex;
5696 endvertex = surface->num_firstvertex + surface->num_vertices;
5697 for (;j < texturenumsurfaces;j++)
5699 surface2 = texturesurfacelist[j];
5700 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5702 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5703 batchtriangles += surface2->num_triangles;
5704 firstvertex = min(firstvertex, surface2->num_firstvertex);
5705 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5707 surface2 = texturesurfacelist[j-1];
5708 numvertices = endvertex - firstvertex;
5709 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5712 else if (r_batchmode.integer == 1)
5714 for (i = 0;i < texturenumsurfaces;i = j)
5716 surface = texturesurfacelist[i];
5717 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5718 if (texturesurfacelist[j] != surface2)
5720 surface2 = texturesurfacelist[j-1];
5721 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5722 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5723 GL_LockArrays(surface->num_firstvertex, numvertices);
5724 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5729 for (i = 0;i < texturenumsurfaces;i++)
5731 surface = texturesurfacelist[i];
5732 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5733 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);
5738 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5740 int i, planeindex, vertexindex;
5744 r_waterstate_waterplane_t *p, *bestp;
5745 msurface_t *surface;
5746 if (r_waterstate.renderingscene)
5748 for (i = 0;i < texturenumsurfaces;i++)
5750 surface = texturesurfacelist[i];
5751 if (lightmaptexunit >= 0)
5752 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5753 if (deluxemaptexunit >= 0)
5754 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5755 // pick the closest matching water plane
5758 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5761 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5763 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5764 d += fabs(PlaneDiff(vert, &p->plane));
5766 if (bestd > d || !bestp)
5774 if (refractiontexunit >= 0)
5775 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5776 if (reflectiontexunit >= 0)
5777 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5781 if (refractiontexunit >= 0)
5782 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5783 if (reflectiontexunit >= 0)
5784 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5786 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5787 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);
5791 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5795 const msurface_t *surface = texturesurfacelist[0];
5796 const msurface_t *surface2;
5801 // TODO: lock all array ranges before render, rather than on each surface
5802 if (texturenumsurfaces == 1)
5804 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5805 if (deluxemaptexunit >= 0)
5806 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5807 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5808 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);
5810 else if (r_batchmode.integer == 2)
5812 #define MAXBATCHTRIANGLES 4096
5813 int batchtriangles = 0;
5814 int batchelements[MAXBATCHTRIANGLES*3];
5815 for (i = 0;i < texturenumsurfaces;i = j)
5817 surface = texturesurfacelist[i];
5818 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5819 if (deluxemaptexunit >= 0)
5820 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5822 if (surface->num_triangles > MAXBATCHTRIANGLES)
5824 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);
5827 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5828 batchtriangles = surface->num_triangles;
5829 firstvertex = surface->num_firstvertex;
5830 endvertex = surface->num_firstvertex + surface->num_vertices;
5831 for (;j < texturenumsurfaces;j++)
5833 surface2 = texturesurfacelist[j];
5834 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5836 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5837 batchtriangles += surface2->num_triangles;
5838 firstvertex = min(firstvertex, surface2->num_firstvertex);
5839 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5841 surface2 = texturesurfacelist[j-1];
5842 numvertices = endvertex - firstvertex;
5843 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5846 else if (r_batchmode.integer == 1)
5849 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5850 for (i = 0;i < texturenumsurfaces;i = j)
5852 surface = texturesurfacelist[i];
5853 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5854 if (texturesurfacelist[j] != surface2)
5856 Con_Printf(" %i", j - i);
5859 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5861 for (i = 0;i < texturenumsurfaces;i = j)
5863 surface = texturesurfacelist[i];
5864 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5865 if (deluxemaptexunit >= 0)
5866 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5867 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5868 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5871 Con_Printf(" %i", j - i);
5873 surface2 = texturesurfacelist[j-1];
5874 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5875 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5876 GL_LockArrays(surface->num_firstvertex, numvertices);
5877 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5885 for (i = 0;i < texturenumsurfaces;i++)
5887 surface = texturesurfacelist[i];
5888 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5889 if (deluxemaptexunit >= 0)
5890 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5891 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5892 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);
5897 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5900 int texturesurfaceindex;
5901 if (r_showsurfaces.integer == 2)
5903 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5905 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5906 for (j = 0;j < surface->num_triangles;j++)
5908 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5909 GL_Color(f, f, f, 1);
5910 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5916 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5918 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5919 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5920 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);
5921 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5922 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);
5927 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5929 int texturesurfaceindex;
5932 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5934 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5935 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)
5943 rsurface.lightmapcolor4f = rsurface.array_color4f;
5944 rsurface.lightmapcolor4f_bufferobject = 0;
5945 rsurface.lightmapcolor4f_bufferoffset = 0;
5948 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5950 int texturesurfaceindex;
5954 if (rsurface.lightmapcolor4f)
5956 // generate color arrays for the surfaces in this list
5957 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5960 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)
5962 f = FogPoint_Model(v);
5972 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5974 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5975 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)
5977 f = FogPoint_Model(v);
5985 rsurface.lightmapcolor4f = rsurface.array_color4f;
5986 rsurface.lightmapcolor4f_bufferobject = 0;
5987 rsurface.lightmapcolor4f_bufferoffset = 0;
5990 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5992 int texturesurfaceindex;
5996 if (!rsurface.lightmapcolor4f)
5998 // generate color arrays for the surfaces in this list
5999 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6001 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6002 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)
6004 f = FogPoint_Model(v);
6005 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6006 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6007 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6011 rsurface.lightmapcolor4f = rsurface.array_color4f;
6012 rsurface.lightmapcolor4f_bufferobject = 0;
6013 rsurface.lightmapcolor4f_bufferoffset = 0;
6016 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6018 int texturesurfaceindex;
6021 if (!rsurface.lightmapcolor4f)
6023 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6025 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6026 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)
6034 rsurface.lightmapcolor4f = rsurface.array_color4f;
6035 rsurface.lightmapcolor4f_bufferobject = 0;
6036 rsurface.lightmapcolor4f_bufferoffset = 0;
6039 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6041 int texturesurfaceindex;
6044 if (!rsurface.lightmapcolor4f)
6046 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6048 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6049 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)
6051 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6052 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6053 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6057 rsurface.lightmapcolor4f = rsurface.array_color4f;
6058 rsurface.lightmapcolor4f_bufferobject = 0;
6059 rsurface.lightmapcolor4f_bufferoffset = 0;
6062 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6065 rsurface.lightmapcolor4f = NULL;
6066 rsurface.lightmapcolor4f_bufferobject = 0;
6067 rsurface.lightmapcolor4f_bufferoffset = 0;
6068 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6069 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6070 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6071 GL_Color(r, g, b, a);
6072 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6075 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6077 // TODO: optimize applyfog && applycolor case
6078 // just apply fog if necessary, and tint the fog color array if necessary
6079 rsurface.lightmapcolor4f = NULL;
6080 rsurface.lightmapcolor4f_bufferobject = 0;
6081 rsurface.lightmapcolor4f_bufferoffset = 0;
6082 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6083 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6084 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6085 GL_Color(r, g, b, a);
6086 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6089 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6091 int texturesurfaceindex;
6095 if (texturesurfacelist[0]->lightmapinfo)
6097 // generate color arrays for the surfaces in this list
6098 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6100 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6101 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6103 if (surface->lightmapinfo->samples)
6105 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6106 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6107 VectorScale(lm, scale, c);
6108 if (surface->lightmapinfo->styles[1] != 255)
6110 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6112 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6113 VectorMA(c, scale, lm, c);
6114 if (surface->lightmapinfo->styles[2] != 255)
6117 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6118 VectorMA(c, scale, lm, c);
6119 if (surface->lightmapinfo->styles[3] != 255)
6122 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6123 VectorMA(c, scale, lm, c);
6133 rsurface.lightmapcolor4f = rsurface.array_color4f;
6134 rsurface.lightmapcolor4f_bufferobject = 0;
6135 rsurface.lightmapcolor4f_bufferoffset = 0;
6139 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6140 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6141 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6143 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6144 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6145 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6146 GL_Color(r, g, b, a);
6147 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6150 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6152 int texturesurfaceindex;
6155 float *v, *c, *c2, alpha;
6156 vec3_t ambientcolor;
6157 vec3_t diffusecolor;
6161 VectorCopy(rsurface.modellight_lightdir, lightdir);
6162 f = 0.5f * r_refdef.lightmapintensity;
6163 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6164 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6165 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6166 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6167 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6168 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6170 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6172 // generate color arrays for the surfaces in this list
6173 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6175 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6176 int numverts = surface->num_vertices;
6177 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6178 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6179 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6180 // q3-style directional shading
6181 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6183 if ((f = DotProduct(c2, lightdir)) > 0)
6184 VectorMA(ambientcolor, f, diffusecolor, c);
6186 VectorCopy(ambientcolor, c);
6194 rsurface.lightmapcolor4f = rsurface.array_color4f;
6195 rsurface.lightmapcolor4f_bufferobject = 0;
6196 rsurface.lightmapcolor4f_bufferoffset = 0;
6197 *applycolor = false;
6201 *r = ambientcolor[0];
6202 *g = ambientcolor[1];
6203 *b = ambientcolor[2];
6204 rsurface.lightmapcolor4f = NULL;
6205 rsurface.lightmapcolor4f_bufferobject = 0;
6206 rsurface.lightmapcolor4f_bufferoffset = 0;
6210 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6212 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6213 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6214 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6215 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6216 GL_Color(r, g, b, a);
6217 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6220 void RSurf_SetupDepthAndCulling(void)
6222 // submodels are biased to avoid z-fighting with world surfaces that they
6223 // may be exactly overlapping (avoids z-fighting artifacts on certain
6224 // doors and things in Quake maps)
6225 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6226 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6227 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6228 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6231 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6233 // transparent sky would be ridiculous
6234 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6236 R_SetupGenericShader(false);
6239 skyrendernow = false;
6240 // we have to force off the water clipping plane while rendering sky
6244 // restore entity matrix
6245 R_Mesh_Matrix(&rsurface.matrix);
6247 RSurf_SetupDepthAndCulling();
6249 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6250 // skymasking on them, and Quake3 never did sky masking (unlike
6251 // software Quake and software Quake2), so disable the sky masking
6252 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6253 // and skymasking also looks very bad when noclipping outside the
6254 // level, so don't use it then either.
6255 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6257 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6258 R_Mesh_ColorPointer(NULL, 0, 0);
6259 R_Mesh_ResetTextureState();
6260 if (skyrendermasked)
6262 R_SetupDepthOrShadowShader();
6263 // depth-only (masking)
6264 GL_ColorMask(0,0,0,0);
6265 // just to make sure that braindead drivers don't draw
6266 // anything despite that colormask...
6267 GL_BlendFunc(GL_ZERO, GL_ONE);
6271 R_SetupGenericShader(false);
6273 GL_BlendFunc(GL_ONE, GL_ZERO);
6275 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6276 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6277 if (skyrendermasked)
6278 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6280 R_Mesh_ResetTextureState();
6281 GL_Color(1, 1, 1, 1);
6284 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6286 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6289 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6290 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6291 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6292 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6293 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6294 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6295 if (rsurface.texture->backgroundcurrentskinframe)
6297 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6298 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6299 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6300 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6302 if(rsurface.texture->colormapping)
6304 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6305 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6307 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6308 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6309 R_Mesh_ColorPointer(NULL, 0, 0);
6311 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6313 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6315 // render background
6316 GL_BlendFunc(GL_ONE, GL_ZERO);
6318 GL_AlphaTest(false);
6320 GL_Color(1, 1, 1, 1);
6321 R_Mesh_ColorPointer(NULL, 0, 0);
6323 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6324 if (r_glsl_permutation)
6326 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6327 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6328 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6329 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6330 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6331 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6332 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);
6334 GL_LockArrays(0, 0);
6336 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6337 GL_DepthMask(false);
6338 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6339 R_Mesh_ColorPointer(NULL, 0, 0);
6341 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6342 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6343 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6346 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6347 if (!r_glsl_permutation)
6350 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6351 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6352 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6353 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6354 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6355 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6357 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6359 GL_BlendFunc(GL_ONE, GL_ZERO);
6361 GL_AlphaTest(false);
6365 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6366 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6367 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6370 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6372 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6373 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);
6375 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6379 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6380 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);
6382 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6384 GL_LockArrays(0, 0);
6387 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6389 // OpenGL 1.3 path - anything not completely ancient
6390 int texturesurfaceindex;
6391 qboolean applycolor;
6395 const texturelayer_t *layer;
6396 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6398 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6401 int layertexrgbscale;
6402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6404 if (layerindex == 0)
6408 GL_AlphaTest(false);
6409 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6412 GL_DepthMask(layer->depthmask && writedepth);
6413 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6414 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6416 layertexrgbscale = 4;
6417 VectorScale(layer->color, 0.25f, layercolor);
6419 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6421 layertexrgbscale = 2;
6422 VectorScale(layer->color, 0.5f, layercolor);
6426 layertexrgbscale = 1;
6427 VectorScale(layer->color, 1.0f, layercolor);
6429 layercolor[3] = layer->color[3];
6430 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6431 R_Mesh_ColorPointer(NULL, 0, 0);
6432 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6433 switch (layer->type)
6435 case TEXTURELAYERTYPE_LITTEXTURE:
6436 memset(&m, 0, sizeof(m));
6437 m.tex[0] = R_GetTexture(r_texture_white);
6438 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6439 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6440 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6441 m.tex[1] = R_GetTexture(layer->texture);
6442 m.texmatrix[1] = layer->texmatrix;
6443 m.texrgbscale[1] = layertexrgbscale;
6444 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6445 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6446 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6447 R_Mesh_TextureState(&m);
6448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6449 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6450 else if (rsurface.uselightmaptexture)
6451 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6453 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6455 case TEXTURELAYERTYPE_TEXTURE:
6456 memset(&m, 0, sizeof(m));
6457 m.tex[0] = R_GetTexture(layer->texture);
6458 m.texmatrix[0] = layer->texmatrix;
6459 m.texrgbscale[0] = layertexrgbscale;
6460 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6461 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6462 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6463 R_Mesh_TextureState(&m);
6464 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6466 case TEXTURELAYERTYPE_FOG:
6467 memset(&m, 0, sizeof(m));
6468 m.texrgbscale[0] = layertexrgbscale;
6471 m.tex[0] = R_GetTexture(layer->texture);
6472 m.texmatrix[0] = layer->texmatrix;
6473 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6474 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6475 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6477 R_Mesh_TextureState(&m);
6478 // generate a color array for the fog pass
6479 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6480 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6484 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6485 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)
6487 f = 1 - FogPoint_Model(v);
6488 c[0] = layercolor[0];
6489 c[1] = layercolor[1];
6490 c[2] = layercolor[2];
6491 c[3] = f * layercolor[3];
6494 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6497 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6499 GL_LockArrays(0, 0);
6502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6504 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6505 GL_AlphaTest(false);
6509 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6511 // OpenGL 1.1 - crusty old voodoo path
6512 int texturesurfaceindex;
6516 const texturelayer_t *layer;
6517 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6519 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6521 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6523 if (layerindex == 0)
6527 GL_AlphaTest(false);
6528 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6531 GL_DepthMask(layer->depthmask && writedepth);
6532 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6533 R_Mesh_ColorPointer(NULL, 0, 0);
6534 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6535 switch (layer->type)
6537 case TEXTURELAYERTYPE_LITTEXTURE:
6538 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6540 // two-pass lit texture with 2x rgbscale
6541 // first the lightmap pass
6542 memset(&m, 0, sizeof(m));
6543 m.tex[0] = R_GetTexture(r_texture_white);
6544 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6545 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6546 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6547 R_Mesh_TextureState(&m);
6548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6549 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6550 else if (rsurface.uselightmaptexture)
6551 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6553 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6554 GL_LockArrays(0, 0);
6555 // then apply the texture to it
6556 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6557 memset(&m, 0, sizeof(m));
6558 m.tex[0] = R_GetTexture(layer->texture);
6559 m.texmatrix[0] = layer->texmatrix;
6560 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6561 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6562 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6563 R_Mesh_TextureState(&m);
6564 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);
6568 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6569 memset(&m, 0, sizeof(m));
6570 m.tex[0] = R_GetTexture(layer->texture);
6571 m.texmatrix[0] = layer->texmatrix;
6572 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6573 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6574 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6575 R_Mesh_TextureState(&m);
6576 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6577 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);
6579 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);
6582 case TEXTURELAYERTYPE_TEXTURE:
6583 // singletexture unlit texture with transparency support
6584 memset(&m, 0, sizeof(m));
6585 m.tex[0] = R_GetTexture(layer->texture);
6586 m.texmatrix[0] = layer->texmatrix;
6587 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6588 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6589 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6590 R_Mesh_TextureState(&m);
6591 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);
6593 case TEXTURELAYERTYPE_FOG:
6594 // singletexture fogging
6595 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6598 memset(&m, 0, sizeof(m));
6599 m.tex[0] = R_GetTexture(layer->texture);
6600 m.texmatrix[0] = layer->texmatrix;
6601 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6602 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6603 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6604 R_Mesh_TextureState(&m);
6607 R_Mesh_ResetTextureState();
6608 // generate a color array for the fog pass
6609 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6613 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6614 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)
6616 f = 1 - FogPoint_Model(v);
6617 c[0] = layer->color[0];
6618 c[1] = layer->color[1];
6619 c[2] = layer->color[2];
6620 c[3] = f * layer->color[3];
6623 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6626 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6628 GL_LockArrays(0, 0);
6631 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6633 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6634 GL_AlphaTest(false);
6638 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6642 GL_AlphaTest(false);
6643 R_Mesh_ColorPointer(NULL, 0, 0);
6644 R_Mesh_ResetTextureState();
6645 R_SetupGenericShader(false);
6647 if(rsurface.texture && rsurface.texture->currentskinframe)
6648 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6657 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6659 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6660 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6661 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6664 // brighten it up (as texture value 127 means "unlit")
6665 c[0] *= 2 * r_refdef.view.colorscale;
6666 c[1] *= 2 * r_refdef.view.colorscale;
6667 c[2] *= 2 * r_refdef.view.colorscale;
6669 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6670 c[3] *= r_wateralpha.value;
6672 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6674 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6675 GL_DepthMask(false);
6677 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6679 GL_BlendFunc(GL_ONE, GL_ONE);
6680 GL_DepthMask(false);
6682 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6684 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6685 GL_DepthMask(false);
6687 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6689 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6690 GL_DepthMask(false);
6694 GL_BlendFunc(GL_ONE, GL_ZERO);
6695 GL_DepthMask(writedepth);
6698 rsurface.lightmapcolor4f = NULL;
6700 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6702 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6704 rsurface.lightmapcolor4f = NULL;
6705 rsurface.lightmapcolor4f_bufferobject = 0;
6706 rsurface.lightmapcolor4f_bufferoffset = 0;
6708 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6710 qboolean applycolor = true;
6713 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6715 r_refdef.lightmapintensity = 1;
6716 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6717 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6721 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6723 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6724 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6725 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6728 if(!rsurface.lightmapcolor4f)
6729 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6731 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6732 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6733 if(r_refdef.fogenabled)
6734 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6736 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6737 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6740 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6743 RSurf_SetupDepthAndCulling();
6744 if (r_showsurfaces.integer == 3)
6745 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6746 else if (r_glsl.integer && gl_support_fragment_shader)
6747 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6748 else if (gl_combine.integer && r_textureunits.integer >= 2)
6749 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6751 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6755 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6758 RSurf_SetupDepthAndCulling();
6759 if (r_showsurfaces.integer == 3)
6760 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6761 else if (r_glsl.integer && gl_support_fragment_shader)
6762 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6763 else if (gl_combine.integer && r_textureunits.integer >= 2)
6764 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6766 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6770 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6773 int texturenumsurfaces, endsurface;
6775 msurface_t *surface;
6776 msurface_t *texturesurfacelist[1024];
6778 // if the model is static it doesn't matter what value we give for
6779 // wantnormals and wanttangents, so this logic uses only rules applicable
6780 // to a model, knowing that they are meaningless otherwise
6781 if (ent == r_refdef.scene.worldentity)
6782 RSurf_ActiveWorldEntity();
6783 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6784 RSurf_ActiveModelEntity(ent, false, false);
6786 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6788 for (i = 0;i < numsurfaces;i = j)
6791 surface = rsurface.modelsurfaces + surfacelist[i];
6792 texture = surface->texture;
6793 rsurface.texture = R_GetCurrentTexture(texture);
6794 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6795 // scan ahead until we find a different texture
6796 endsurface = min(i + 1024, numsurfaces);
6797 texturenumsurfaces = 0;
6798 texturesurfacelist[texturenumsurfaces++] = surface;
6799 for (;j < endsurface;j++)
6801 surface = rsurface.modelsurfaces + surfacelist[j];
6802 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6804 texturesurfacelist[texturenumsurfaces++] = surface;
6806 // render the range of surfaces
6807 if (ent == r_refdef.scene.worldentity)
6808 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6810 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6812 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6813 GL_AlphaTest(false);
6816 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6818 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6822 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6824 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6826 RSurf_SetupDepthAndCulling();
6827 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6828 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6830 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6832 RSurf_SetupDepthAndCulling();
6833 GL_AlphaTest(false);
6834 R_Mesh_ColorPointer(NULL, 0, 0);
6835 R_Mesh_ResetTextureState();
6836 R_SetupGenericShader(false);
6837 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6839 GL_BlendFunc(GL_ONE, GL_ZERO);
6840 GL_Color(0, 0, 0, 1);
6841 GL_DepthTest(writedepth);
6842 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6844 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6846 RSurf_SetupDepthAndCulling();
6847 GL_AlphaTest(false);
6848 R_Mesh_ColorPointer(NULL, 0, 0);
6849 R_Mesh_ResetTextureState();
6850 R_SetupGenericShader(false);
6851 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6853 GL_BlendFunc(GL_ONE, GL_ZERO);
6855 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6857 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6858 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6859 else if (!rsurface.texture->currentnumlayers)
6861 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6863 // transparent surfaces get pushed off into the transparent queue
6864 int surfacelistindex;
6865 const msurface_t *surface;
6866 vec3_t tempcenter, center;
6867 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6869 surface = texturesurfacelist[surfacelistindex];
6870 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6871 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6872 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6873 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6874 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6879 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6880 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6885 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6889 // break the surface list down into batches by texture and use of lightmapping
6890 for (i = 0;i < numsurfaces;i = j)
6893 // texture is the base texture pointer, rsurface.texture is the
6894 // current frame/skin the texture is directing us to use (for example
6895 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6896 // use skin 1 instead)
6897 texture = surfacelist[i]->texture;
6898 rsurface.texture = R_GetCurrentTexture(texture);
6899 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6900 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6902 // if this texture is not the kind we want, skip ahead to the next one
6903 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6907 // simply scan ahead until we find a different texture or lightmap state
6908 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6910 // render the range of surfaces
6911 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6915 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6920 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6922 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6924 RSurf_SetupDepthAndCulling();
6925 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6926 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6928 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6930 RSurf_SetupDepthAndCulling();
6931 GL_AlphaTest(false);
6932 R_Mesh_ColorPointer(NULL, 0, 0);
6933 R_Mesh_ResetTextureState();
6934 R_SetupGenericShader(false);
6935 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6937 GL_BlendFunc(GL_ONE, GL_ZERO);
6938 GL_Color(0, 0, 0, 1);
6939 GL_DepthTest(writedepth);
6940 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6942 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6944 RSurf_SetupDepthAndCulling();
6945 GL_AlphaTest(false);
6946 R_Mesh_ColorPointer(NULL, 0, 0);
6947 R_Mesh_ResetTextureState();
6948 R_SetupGenericShader(false);
6949 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6951 GL_BlendFunc(GL_ONE, GL_ZERO);
6953 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6955 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6956 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6957 else if (!rsurface.texture->currentnumlayers)
6959 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6961 // transparent surfaces get pushed off into the transparent queue
6962 int surfacelistindex;
6963 const msurface_t *surface;
6964 vec3_t tempcenter, center;
6965 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6967 surface = texturesurfacelist[surfacelistindex];
6968 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6969 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6970 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6971 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6972 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6977 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6978 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6983 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6987 // break the surface list down into batches by texture and use of lightmapping
6988 for (i = 0;i < numsurfaces;i = j)
6991 // texture is the base texture pointer, rsurface.texture is the
6992 // current frame/skin the texture is directing us to use (for example
6993 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6994 // use skin 1 instead)
6995 texture = surfacelist[i]->texture;
6996 rsurface.texture = R_GetCurrentTexture(texture);
6997 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6998 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7000 // if this texture is not the kind we want, skip ahead to the next one
7001 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7005 // simply scan ahead until we find a different texture or lightmap state
7006 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7008 // render the range of surfaces
7009 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7013 float locboxvertex3f[6*4*3] =
7015 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7016 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7017 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7018 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7019 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7020 1,0,0, 0,0,0, 0,1,0, 1,1,0
7023 unsigned short locboxelements[6*2*3] =
7033 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7036 cl_locnode_t *loc = (cl_locnode_t *)ent;
7038 float vertex3f[6*4*3];
7040 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7041 GL_DepthMask(false);
7042 GL_DepthRange(0, 1);
7043 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7045 GL_CullFace(GL_NONE);
7046 R_Mesh_Matrix(&identitymatrix);
7048 R_Mesh_VertexPointer(vertex3f, 0, 0);
7049 R_Mesh_ColorPointer(NULL, 0, 0);
7050 R_Mesh_ResetTextureState();
7051 R_SetupGenericShader(false);
7054 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7055 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7056 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7057 surfacelist[0] < 0 ? 0.5f : 0.125f);
7059 if (VectorCompare(loc->mins, loc->maxs))
7061 VectorSet(size, 2, 2, 2);
7062 VectorMA(loc->mins, -0.5f, size, mins);
7066 VectorCopy(loc->mins, mins);
7067 VectorSubtract(loc->maxs, loc->mins, size);
7070 for (i = 0;i < 6*4*3;)
7071 for (j = 0;j < 3;j++, i++)
7072 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7074 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7077 void R_DrawLocs(void)
7080 cl_locnode_t *loc, *nearestloc;
7082 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7083 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7085 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7086 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7090 void R_DrawDebugModel(entity_render_t *ent)
7092 int i, j, k, l, flagsmask;
7093 const int *elements;
7095 msurface_t *surface;
7096 dp_model_t *model = ent->model;
7099 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7101 R_Mesh_ColorPointer(NULL, 0, 0);
7102 R_Mesh_ResetTextureState();
7103 R_SetupGenericShader(false);
7104 GL_DepthRange(0, 1);
7105 GL_DepthTest(!r_showdisabledepthtest.integer);
7106 GL_DepthMask(false);
7107 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7109 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7111 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7112 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7114 if (brush->colbrushf && brush->colbrushf->numtriangles)
7116 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7117 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);
7118 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7121 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7123 if (surface->num_collisiontriangles)
7125 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7126 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);
7127 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7132 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7134 if (r_showtris.integer || r_shownormals.integer)
7136 if (r_showdisabledepthtest.integer)
7138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7139 GL_DepthMask(false);
7143 GL_BlendFunc(GL_ONE, GL_ZERO);
7146 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7148 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7150 rsurface.texture = R_GetCurrentTexture(surface->texture);
7151 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7153 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7154 if (r_showtris.value > 0)
7156 if (!rsurface.texture->currentlayers->depthmask)
7157 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7158 else if (ent == r_refdef.scene.worldentity)
7159 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7161 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7162 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7163 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7164 R_Mesh_ColorPointer(NULL, 0, 0);
7165 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7166 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7167 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7168 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);
7169 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7172 if (r_shownormals.value < 0)
7175 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7177 VectorCopy(rsurface.vertex3f + l * 3, v);
7178 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7179 qglVertex3f(v[0], v[1], v[2]);
7180 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7181 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7182 qglVertex3f(v[0], v[1], v[2]);
7187 if (r_shownormals.value > 0)
7190 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7192 VectorCopy(rsurface.vertex3f + l * 3, v);
7193 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7194 qglVertex3f(v[0], v[1], v[2]);
7195 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7196 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7197 qglVertex3f(v[0], v[1], v[2]);
7202 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7204 VectorCopy(rsurface.vertex3f + l * 3, v);
7205 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7206 qglVertex3f(v[0], v[1], v[2]);
7207 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7208 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7209 qglVertex3f(v[0], v[1], v[2]);
7214 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7216 VectorCopy(rsurface.vertex3f + l * 3, v);
7217 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7218 qglVertex3f(v[0], v[1], v[2]);
7219 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7220 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7221 qglVertex3f(v[0], v[1], v[2]);
7228 rsurface.texture = NULL;
7232 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7233 int r_maxsurfacelist = 0;
7234 msurface_t **r_surfacelist = NULL;
7235 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7237 int i, j, endj, f, flagsmask;
7239 dp_model_t *model = r_refdef.scene.worldmodel;
7240 msurface_t *surfaces;
7241 unsigned char *update;
7242 int numsurfacelist = 0;
7246 if (r_maxsurfacelist < model->num_surfaces)
7248 r_maxsurfacelist = model->num_surfaces;
7250 Mem_Free(r_surfacelist);
7251 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7254 RSurf_ActiveWorldEntity();
7256 surfaces = model->data_surfaces;
7257 update = model->brushq1.lightmapupdateflags;
7259 // update light styles on this submodel
7260 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7262 model_brush_lightstyleinfo_t *style;
7263 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7265 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7267 int *list = style->surfacelist;
7268 style->value = r_refdef.scene.lightstylevalue[style->style];
7269 for (j = 0;j < style->numsurfaces;j++)
7270 update[list[j]] = true;
7275 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7279 R_DrawDebugModel(r_refdef.scene.worldentity);
7280 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7286 rsurface.uselightmaptexture = false;
7287 rsurface.texture = NULL;
7288 rsurface.rtlight = NULL;
7290 // add visible surfaces to draw list
7291 for (i = 0;i < model->nummodelsurfaces;i++)
7293 j = model->sortedmodelsurfaces[i];
7294 if (r_refdef.viewcache.world_surfacevisible[j])
7295 r_surfacelist[numsurfacelist++] = surfaces + j;
7297 // update lightmaps if needed
7299 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7300 if (r_refdef.viewcache.world_surfacevisible[j])
7302 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7303 // don't do anything if there were no surfaces
7304 if (!numsurfacelist)
7306 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7309 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7310 GL_AlphaTest(false);
7312 // add to stats if desired
7313 if (r_speeds.integer && !skysurfaces && !depthonly)
7315 r_refdef.stats.world_surfaces += numsurfacelist;
7316 for (j = 0;j < numsurfacelist;j++)
7317 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7319 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7322 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7324 int i, j, endj, f, flagsmask;
7326 dp_model_t *model = ent->model;
7327 msurface_t *surfaces;
7328 unsigned char *update;
7329 int numsurfacelist = 0;
7333 if (r_maxsurfacelist < model->num_surfaces)
7335 r_maxsurfacelist = model->num_surfaces;
7337 Mem_Free(r_surfacelist);
7338 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7341 // if the model is static it doesn't matter what value we give for
7342 // wantnormals and wanttangents, so this logic uses only rules applicable
7343 // to a model, knowing that they are meaningless otherwise
7344 if (ent == r_refdef.scene.worldentity)
7345 RSurf_ActiveWorldEntity();
7346 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7347 RSurf_ActiveModelEntity(ent, false, false);
7349 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7351 surfaces = model->data_surfaces;
7352 update = model->brushq1.lightmapupdateflags;
7354 // update light styles
7355 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7357 model_brush_lightstyleinfo_t *style;
7358 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7360 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7362 int *list = style->surfacelist;
7363 style->value = r_refdef.scene.lightstylevalue[style->style];
7364 for (j = 0;j < style->numsurfaces;j++)
7365 update[list[j]] = true;
7370 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7374 R_DrawDebugModel(ent);
7375 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7381 rsurface.uselightmaptexture = false;
7382 rsurface.texture = NULL;
7383 rsurface.rtlight = NULL;
7385 // add visible surfaces to draw list
7386 for (i = 0;i < model->nummodelsurfaces;i++)
7387 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7388 // don't do anything if there were no surfaces
7389 if (!numsurfacelist)
7391 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7394 // update lightmaps if needed
7396 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7398 R_BuildLightMap(ent, surfaces + j);
7399 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7400 GL_AlphaTest(false);
7402 // add to stats if desired
7403 if (r_speeds.integer && !skysurfaces && !depthonly)
7405 r_refdef.stats.entities_surfaces += numsurfacelist;
7406 for (j = 0;j < numsurfacelist;j++)
7407 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7409 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity