2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 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"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 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)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 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"};
57 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"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 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"};
60 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"};
61 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"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 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 in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlightning = {CVAR_SAVE, "r_shadows_drawafterrtlightning", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 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"};
82 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"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 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)"};
99 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)"};
100 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
101 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
102 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
103 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
104 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)"};
105 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)"};
106 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)"};
107 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)"};
108 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)"};
110 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)"};
111 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
112 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"};
113 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
114 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
116 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
117 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
118 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
119 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
121 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
122 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
123 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
124 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
125 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
126 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
127 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
129 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
130 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
131 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
132 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)"};
134 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"};
136 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"};
138 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
140 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
141 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
142 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"};
143 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
144 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
145 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
146 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
148 extern cvar_t v_glslgamma;
150 extern qboolean v_flipped_state;
152 static struct r_bloomstate_s
157 int bloomwidth, bloomheight;
159 int screentexturewidth, screentextureheight;
160 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
162 int bloomtexturewidth, bloomtextureheight;
163 rtexture_t *texture_bloom;
165 // arrays for rendering the screen passes
166 float screentexcoord2f[8];
167 float bloomtexcoord2f[8];
168 float offsettexcoord2f[8];
172 r_waterstate_t r_waterstate;
174 /// shadow volume bsp struct with automatically growing nodes buffer
177 rtexture_t *r_texture_blanknormalmap;
178 rtexture_t *r_texture_white;
179 rtexture_t *r_texture_grey128;
180 rtexture_t *r_texture_black;
181 rtexture_t *r_texture_notexture;
182 rtexture_t *r_texture_whitecube;
183 rtexture_t *r_texture_normalizationcube;
184 rtexture_t *r_texture_fogattenuation;
185 rtexture_t *r_texture_gammaramps;
186 unsigned int r_texture_gammaramps_serial;
187 //rtexture_t *r_texture_fogintensity;
189 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
190 unsigned int r_numqueries;
191 unsigned int r_maxqueries;
193 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
194 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
196 /// vertex coordinates for a quad that covers the screen exactly
197 const static float r_screenvertex3f[12] =
205 extern void R_DrawModelShadows(void);
207 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
210 for (i = 0;i < verts;i++)
221 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
224 for (i = 0;i < verts;i++)
234 // FIXME: move this to client?
237 if (gamemode == GAME_NEHAHRA)
239 Cvar_Set("gl_fogenable", "0");
240 Cvar_Set("gl_fogdensity", "0.2");
241 Cvar_Set("gl_fogred", "0.3");
242 Cvar_Set("gl_foggreen", "0.3");
243 Cvar_Set("gl_fogblue", "0.3");
245 r_refdef.fog_density = 0;
246 r_refdef.fog_red = 0;
247 r_refdef.fog_green = 0;
248 r_refdef.fog_blue = 0;
249 r_refdef.fog_alpha = 1;
250 r_refdef.fog_start = 0;
251 r_refdef.fog_end = 0;
254 float FogForDistance(vec_t dist)
256 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
260 float FogPoint_World(const vec3_t p)
262 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
265 float FogPoint_Model(const vec3_t p)
267 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
270 static void R_BuildBlankTextures(void)
272 unsigned char data[4];
273 data[2] = 128; // normal X
274 data[1] = 128; // normal Y
275 data[0] = 255; // normal Z
276 data[3] = 128; // height
277 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
282 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 static void R_BuildNoTexture(void)
298 unsigned char pix[16][16][4];
299 // this makes a light grey/dark grey checkerboard texture
300 for (y = 0;y < 16;y++)
302 for (x = 0;x < 16;x++)
304 if ((y < 8) ^ (x < 8))
320 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
323 static void R_BuildWhiteCube(void)
325 unsigned char data[6*1*1*4];
326 memset(data, 255, sizeof(data));
327 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
330 static void R_BuildNormalizationCube(void)
334 vec_t s, t, intensity;
336 unsigned char data[6][NORMSIZE][NORMSIZE][4];
337 for (side = 0;side < 6;side++)
339 for (y = 0;y < NORMSIZE;y++)
341 for (x = 0;x < NORMSIZE;x++)
343 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
344 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
379 intensity = 127.0f / sqrt(DotProduct(v, v));
380 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
381 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
382 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
383 data[side][y][x][3] = 255;
387 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
390 static void R_BuildFogTexture(void)
394 unsigned char data1[FOGWIDTH][4];
395 //unsigned char data2[FOGWIDTH][4];
398 r_refdef.fogmasktable_start = r_refdef.fog_start;
399 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
400 r_refdef.fogmasktable_range = r_refdef.fogrange;
401 r_refdef.fogmasktable_density = r_refdef.fog_density;
403 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
404 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
406 d = (x * r - r_refdef.fogmasktable_start);
407 if(developer.integer >= 100)
408 Con_Printf("%f ", d);
410 if (r_fog_exp2.integer)
411 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
413 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
414 if(developer.integer >= 100)
415 Con_Printf(" : %f ", alpha);
416 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
417 if(developer.integer >= 100)
418 Con_Printf(" = %f\n", alpha);
419 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
422 for (x = 0;x < FOGWIDTH;x++)
424 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
429 //data2[x][0] = 255 - b;
430 //data2[x][1] = 255 - b;
431 //data2[x][2] = 255 - b;
434 if (r_texture_fogattenuation)
436 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
437 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
441 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);
442 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
446 static const char *builtinshaderstring =
447 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
448 "// written by Forest 'LordHavoc' Hale\n"
449 "#ifdef USESHADOWMAPRECT\n"
450 "#extension GL_ARB_texture_rectangle : enable\n"
452 "#ifdef USESHADOWMAPCUBE\n"
453 "#extension GL_EXT_gpu_shader4 : enable\n"
456 "// common definitions between vertex shader and fragment shader:\n"
458 "//#ifdef __GLSL_CG_DATA_TYPES\n"
459 "//# define myhalf half\n"
460 "//# define myhalf2 half2\n"
461 "//# define myhalf3 half3\n"
462 "//# define myhalf4 half4\n"
464 "# define myhalf float\n"
465 "# define myhalf2 vec2\n"
466 "# define myhalf3 vec3\n"
467 "# define myhalf4 vec4\n"
470 "#ifdef MODE_DEPTH_OR_SHADOW\n"
472 "# ifdef VERTEX_SHADER\n"
475 " gl_Position = ftransform();\n"
480 "#ifdef MODE_SHOWDEPTH\n"
481 "# ifdef VERTEX_SHADER\n"
484 " gl_Position = ftransform();\n"
485 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
488 "# ifdef FRAGMENT_SHADER\n"
491 " gl_FragColor = gl_Color;\n"
495 "#else // !MODE_SHOWDEPTH\n"
497 "#ifdef MODE_POSTPROCESS\n"
498 "# ifdef VERTEX_SHADER\n"
501 " gl_FrontColor = gl_Color;\n"
502 " gl_Position = ftransform();\n"
503 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
505 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
509 "# ifdef FRAGMENT_SHADER\n"
511 "uniform sampler2D Texture_First;\n"
513 "uniform sampler2D Texture_Second;\n"
515 "#ifdef USEGAMMARAMPS\n"
516 "uniform sampler2D Texture_GammaRamps;\n"
518 "#ifdef USESATURATION\n"
519 "uniform float Saturation;\n"
521 "#ifdef USEVERTEXTEXTUREBLEND\n"
522 "uniform vec4 TintColor;\n"
524 "#ifdef USECOLORMOD\n"
525 "uniform vec3 Gamma;\n"
527 "//uncomment these if you want to use them:\n"
528 "uniform vec4 UserVec1;\n"
529 "// uniform vec4 UserVec2;\n"
530 "// uniform vec4 UserVec3;\n"
531 "// uniform vec4 UserVec4;\n"
532 "// uniform float ClientTime;\n"
533 "uniform vec2 PixelSize;\n"
536 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
538 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
540 "#ifdef USEVERTEXTEXTUREBLEND\n"
541 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
544 "#ifdef USEPOSTPROCESSING\n"
545 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
546 "// 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"
547 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
548 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
549 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
550 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
551 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
552 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
555 "#ifdef USESATURATION\n"
556 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
557 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
558 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
559 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
562 "#ifdef USEGAMMARAMPS\n"
563 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
564 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
565 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
572 "#ifdef MODE_GENERIC\n"
573 "# ifdef VERTEX_SHADER\n"
576 " gl_FrontColor = gl_Color;\n"
577 "# ifdef USEDIFFUSE\n"
578 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
580 "# ifdef USESPECULAR\n"
581 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
583 " gl_Position = ftransform();\n"
586 "# ifdef FRAGMENT_SHADER\n"
588 "# ifdef USEDIFFUSE\n"
589 "uniform sampler2D Texture_First;\n"
591 "# ifdef USESPECULAR\n"
592 "uniform sampler2D Texture_Second;\n"
597 " gl_FragColor = gl_Color;\n"
598 "# ifdef USEDIFFUSE\n"
599 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
602 "# ifdef USESPECULAR\n"
603 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
605 "# ifdef USECOLORMAPPING\n"
606 " gl_FragColor *= tex2;\n"
609 " gl_FragColor += tex2;\n"
611 "# ifdef USEVERTEXTEXTUREBLEND\n"
612 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
617 "#else // !MODE_GENERIC\n"
619 "varying vec2 TexCoord;\n"
620 "#ifdef USEVERTEXTEXTUREBLEND\n"
621 "varying vec2 TexCoord2;\n"
623 "varying vec2 TexCoordLightmap;\n"
625 "#ifdef MODE_LIGHTSOURCE\n"
626 "varying vec3 CubeVector;\n"
629 "#ifdef MODE_LIGHTSOURCE\n"
630 "varying vec3 LightVector;\n"
632 "#ifdef MODE_LIGHTDIRECTION\n"
633 "varying vec3 LightVector;\n"
636 "varying vec3 EyeVector;\n"
638 "varying vec3 EyeVectorModelSpace;\n"
641 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
642 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
643 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
645 "#ifdef MODE_WATER\n"
646 "varying vec4 ModelViewProjectionPosition;\n"
648 "#ifdef MODE_REFRACTION\n"
649 "varying vec4 ModelViewProjectionPosition;\n"
651 "#ifdef USEREFLECTION\n"
652 "varying vec4 ModelViewProjectionPosition;\n"
659 "// vertex shader specific:\n"
660 "#ifdef VERTEX_SHADER\n"
662 "uniform vec3 LightPosition;\n"
663 "uniform vec3 EyePosition;\n"
664 "uniform vec3 LightDir;\n"
666 "// 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"
670 " gl_FrontColor = gl_Color;\n"
671 " // copy the surface texcoord\n"
672 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
673 "#ifdef USEVERTEXTEXTUREBLEND\n"
674 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
676 "#ifndef MODE_LIGHTSOURCE\n"
677 "# ifndef MODE_LIGHTDIRECTION\n"
678 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
682 "#ifdef MODE_LIGHTSOURCE\n"
683 " // transform vertex position into light attenuation/cubemap space\n"
684 " // (-1 to +1 across the light box)\n"
685 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
687 " // transform unnormalized light direction into tangent space\n"
688 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
689 " // normalize it per pixel)\n"
690 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
691 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
692 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
693 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
696 "#ifdef MODE_LIGHTDIRECTION\n"
697 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
698 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
699 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
702 " // transform unnormalized eye direction into tangent space\n"
704 " vec3 EyeVectorModelSpace;\n"
706 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
707 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
708 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
709 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
711 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
712 " VectorS = gl_MultiTexCoord1.xyz;\n"
713 " VectorT = gl_MultiTexCoord2.xyz;\n"
714 " VectorR = gl_MultiTexCoord3.xyz;\n"
717 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
718 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
719 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
720 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
723 "// transform vertex to camera space, using ftransform to match non-VS\n"
725 " gl_Position = ftransform();\n"
727 "#ifdef MODE_WATER\n"
728 " ModelViewProjectionPosition = gl_Position;\n"
730 "#ifdef MODE_REFRACTION\n"
731 " ModelViewProjectionPosition = gl_Position;\n"
733 "#ifdef USEREFLECTION\n"
734 " ModelViewProjectionPosition = gl_Position;\n"
738 "#endif // VERTEX_SHADER\n"
743 "// fragment shader specific:\n"
744 "#ifdef FRAGMENT_SHADER\n"
746 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
747 "uniform sampler2D Texture_Normal;\n"
748 "uniform sampler2D Texture_Color;\n"
749 "uniform sampler2D Texture_Gloss;\n"
750 "uniform sampler2D Texture_Glow;\n"
751 "uniform sampler2D Texture_SecondaryNormal;\n"
752 "uniform sampler2D Texture_SecondaryColor;\n"
753 "uniform sampler2D Texture_SecondaryGloss;\n"
754 "uniform sampler2D Texture_SecondaryGlow;\n"
755 "uniform sampler2D Texture_Pants;\n"
756 "uniform sampler2D Texture_Shirt;\n"
757 "uniform sampler2D Texture_FogMask;\n"
758 "uniform sampler2D Texture_Lightmap;\n"
759 "uniform sampler2D Texture_Deluxemap;\n"
760 "uniform sampler2D Texture_Refraction;\n"
761 "uniform sampler2D Texture_Reflection;\n"
762 "uniform sampler2D Texture_Attenuation;\n"
763 "uniform samplerCube Texture_Cube;\n"
765 "#define showshadowmap 0\n"
766 "#define useshadowsamplerrect 0\n"
767 "#define useshadowsampler2d 0\n"
768 "#define useshadowsamplercube 1\n"
770 "#ifdef USESHADOWMAPRECT\n"
771 "# if useshadowsamplerrect\n"
772 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
774 "uniform sampler2DRect Texture_ShadowMapRect;\n"
778 "#ifdef USESHADOWMAP2D\n"
779 "# if useshadowsampler2d\n"
780 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
782 "uniform sampler2D Texture_ShadowMap2D;\n"
786 "#ifdef USESHADOWMAPCUBE\n"
787 "# if useshadowsamplercube\n"
788 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
790 "uniform samplerCube Texture_ShadowMapCube;\n"
794 "uniform myhalf3 LightColor;\n"
795 "uniform myhalf3 AmbientColor;\n"
796 "uniform myhalf3 DiffuseColor;\n"
797 "uniform myhalf3 SpecularColor;\n"
798 "uniform myhalf3 Color_Pants;\n"
799 "uniform myhalf3 Color_Shirt;\n"
800 "uniform myhalf3 FogColor;\n"
802 "uniform myhalf4 TintColor;\n"
805 "//#ifdef MODE_WATER\n"
806 "uniform vec4 DistortScaleRefractReflect;\n"
807 "uniform vec4 ScreenScaleRefractReflect;\n"
808 "uniform vec4 ScreenCenterRefractReflect;\n"
809 "uniform myhalf4 RefractColor;\n"
810 "uniform myhalf4 ReflectColor;\n"
811 "uniform myhalf ReflectFactor;\n"
812 "uniform myhalf ReflectOffset;\n"
814 "//# ifdef MODE_REFRACTION\n"
815 "//uniform vec4 DistortScaleRefractReflect;\n"
816 "//uniform vec4 ScreenScaleRefractReflect;\n"
817 "//uniform vec4 ScreenCenterRefractReflect;\n"
818 "//uniform myhalf4 RefractColor;\n"
819 "//# ifdef USEREFLECTION\n"
820 "//uniform myhalf4 ReflectColor;\n"
823 "//# ifdef USEREFLECTION\n"
824 "//uniform vec4 DistortScaleRefractReflect;\n"
825 "//uniform vec4 ScreenScaleRefractReflect;\n"
826 "//uniform vec4 ScreenCenterRefractReflect;\n"
827 "//uniform myhalf4 ReflectColor;\n"
832 "uniform myhalf GlowScale;\n"
833 "uniform myhalf SceneBrightness;\n"
834 "#ifdef USECONTRASTBOOST\n"
835 "uniform myhalf ContrastBoostCoeff;\n"
838 "uniform float OffsetMapping_Scale;\n"
839 "uniform float OffsetMapping_Bias;\n"
840 "uniform float FogRangeRecip;\n"
842 "uniform myhalf AmbientScale;\n"
843 "uniform myhalf DiffuseScale;\n"
844 "uniform myhalf SpecularScale;\n"
845 "uniform myhalf SpecularPower;\n"
847 "#ifdef USEOFFSETMAPPING\n"
848 "vec2 OffsetMapping(vec2 TexCoord)\n"
850 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
851 " // 14 sample relief mapping: linear search and then binary search\n"
852 " // this basically steps forward a small amount repeatedly until it finds\n"
853 " // itself inside solid, then jitters forward and back using decreasing\n"
854 " // amounts to find the impact\n"
855 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
856 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
857 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
858 " vec3 RT = vec3(TexCoord, 1);\n"
859 " OffsetVector *= 0.1;\n"
860 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
861 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
862 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
863 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
864 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
865 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
866 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
867 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
868 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
869 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
870 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
871 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
872 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
873 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
876 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
877 " // this basically moves forward the full distance, and then backs up based\n"
878 " // on height of samples\n"
879 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
880 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
881 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
882 " TexCoord += OffsetVector;\n"
883 " OffsetVector *= 0.333;\n"
884 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
885 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
886 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
887 " return TexCoord;\n"
890 "#endif // USEOFFSETMAPPING\n"
892 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
893 "//float ShadowMap_TextureSize = 1024.0;\n"
894 "//float ShadowMap_BorderSize = 6.0;\n"
895 "//float ShadowMap_NearClip = 0.0001;\n"
896 "//float ShadowMap_FarClip = 1.0;\n"
897 "//float ShadowMap_Bias = ShadowMap_NearClip * 64.0 / ShadowMap_TextureSize;\n"
898 "//vec2 ShadowMap_TextureScale = vec2(0.5, 0.25);\n"
899 "//vec4 ShadowMap_Parameters = vec3(1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, 1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, -(ShadowMap_FarClip + ShadowMap_NearClip) / (ShadowMap_FarClip - ShadowMap_NearClip), -2.0 * ShadowMap_NearClip * ShadowMap_FarClip / (ShadowMap_FarClip - ShadowMap_NearClip));\n"
900 "uniform float ShadowMap_Bias;\n"
901 "uniform vec2 ShadowMap_TextureScale;\n"
902 "uniform vec4 ShadowMap_Parameters;\n"
905 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
906 "vec3 GetShadowMapTC2D(vec3 dir)\n"
908 " vec3 adir = abs(dir);\n"
913 " if (adir.x > adir.y)\n"
915 " if (adir.x > adir.z)\n"
917 " d = 0.5 / adir.x;\n"
918 " if (dir.x >= 0.0)\n"
921 " tc = vec3(-dir.z, -dir.y, -dir.x);\n"
922 " offset = vec3(0.5, 0.5, 0.5);\n"
927 " tc = vec3( dir.z, -dir.y, dir.x);\n"
928 " offset = vec3(1.5, 0.5, 0.5);\n"
933 " d = 0.5 / adir.z;\n"
934 " if (dir.z >= 0.0)\n"
937 " tc = vec3( dir.x, -dir.y, -dir.z);\n"
938 " offset = vec3(0.5, 2.5, 0.5);\n"
943 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
944 " offset = vec3(1.5, 2.5, 0.5);\n"
950 " if (adir.y > adir.z)\n"
952 " d = 0.5 / adir.y;\n"
953 " if (dir.y >= 0.0)\n"
956 " tc = vec3( dir.x, dir.z, -dir.y);\n"
957 " offset = vec3(0.5, 1.5, 0.5);\n"
962 " tc = vec3( dir.x, -dir.z, dir.y);\n"
963 " offset = vec3(1.5, 1.5, 0.5);\n"
968 " d = 0.5 / adir.z;\n"
969 " if (dir.z >= 0.0)\n"
972 " tc = vec3(dir.x, -dir.y, -dir.z);\n"
973 " offset = vec3(0.5, 2.5, 0.5);\n"
978 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
979 " offset = vec3(1.5, 2.5, 0.5);\n"
983 " tc = tc * ShadowMap_Parameters.xyz * d + offset;\n"
984 " tc.xy *= ShadowMap_TextureScale;\n"
985 " tc.z += ShadowMap_Parameters.w * d - ShadowMap_Bias * d;\n"
987 " // experimental method by eihrul, needs overhaul\n"
988 " vec3 ma = vec3(0.0, 0.0, 1.0);\n"
989 " if (adir.x > adir.y)\n"
991 " if (adir.x > adir.z)\n"
992 " ma = vec3(1.0, 0.0, 0.0);\n"
994 " else if (adir.y > adir.z)\n"
995 " ma = vec3(0.0, 1.0, 0.0);\n"
997 " tc.xy = dir.xy - ma.xy*(dir.xy - dir.z);\n"
998 " tc.xy = (tc.xy/dot(ma, dir))*0.5 + 0.5;\n"
999 " tc.z = dot(ma, adir);\n"
1000 " tc.xy = (tc.xy * tcscale + offset) * vec2(0.5, 0.25);\n"
1005 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1007 "#ifdef USESHADOWMAPCUBE\n"
1008 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1010 " vec3 adir = abs(dir);\n"
1011 " float sidedist = max(adir.x, max(adir.y, adir.z));\n"
1012 " return vec4(dir, 0.5 - 0.5 * (ShadowMap_Parameters.z - (-ShadowMap_Bias + ShadowMap_Parameters.w) / sidedist));\n"
1016 "#if !showshadowmap\n"
1017 "# ifdef USESHADOWMAPRECT\n"
1018 "float ShadowMapCompare(vec3 dir)\n"
1020 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1022 "# if useshadowsamplerrect\n"
1023 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).a;\n"
1025 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1031 "# ifdef USESHADOWMAP2D\n"
1032 "float ShadowMapCompare(vec3 dir)\n"
1034 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1036 "# if useshadowsampler2d\n"
1037 " f = shadow2D(Texture_ShadowMap2D, shadowmaptc).a;\n"
1039 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
1045 "# ifdef USESHADOWMAPCUBE\n"
1046 "float ShadowMapCompare(vec3 dir)\n"
1048 " // apply depth texture cubemap as light filter\n"
1049 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1051 "# if useshadowsamplercube\n"
1052 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).a;\n"
1054 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1062 "#ifdef MODE_WATER\n"
1067 "#ifdef USEOFFSETMAPPING\n"
1068 " // apply offsetmapping\n"
1069 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1070 "#define TexCoord TexCoordOffset\n"
1073 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1074 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1075 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1076 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1077 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1080 "#else // !MODE_WATER\n"
1081 "#ifdef MODE_REFRACTION\n"
1083 "// refraction pass\n"
1086 "#ifdef USEOFFSETMAPPING\n"
1087 " // apply offsetmapping\n"
1088 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1089 "#define TexCoord TexCoordOffset\n"
1092 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1093 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1094 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1095 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1098 "#else // !MODE_REFRACTION\n"
1101 "#ifdef USEOFFSETMAPPING\n"
1102 " // apply offsetmapping\n"
1103 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1104 "#define TexCoord TexCoordOffset\n"
1107 " // combine the diffuse textures (base, pants, shirt)\n"
1108 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1109 "#ifdef USECOLORMAPPING\n"
1110 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1112 "#ifdef USEVERTEXTEXTUREBLEND\n"
1113 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1114 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1115 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1116 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1118 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1121 "#ifdef USEDIFFUSE\n"
1122 " // get the surface normal and the gloss color\n"
1123 "# ifdef USEVERTEXTEXTUREBLEND\n"
1124 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1125 "# ifdef USESPECULAR\n"
1126 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1129 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1130 "# ifdef USESPECULAR\n"
1131 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1138 "#ifdef MODE_LIGHTSOURCE\n"
1139 " // light source\n"
1141 " // calculate surface normal, light normal, and specular normal\n"
1142 " // compute color intensity for the two textures (colormap and glossmap)\n"
1143 " // scale by light color and attenuation as efficiently as possible\n"
1144 " // (do as much scalar math as possible rather than vector math)\n"
1145 "# ifdef USEDIFFUSE\n"
1146 " // get the light normal\n"
1147 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1149 "# ifdef USESPECULAR\n"
1150 "# ifndef USEEXACTSPECULARMATH\n"
1151 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1154 " // calculate directional shading\n"
1155 "# ifdef USEEXACTSPECULARMATH\n"
1156 " 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"
1158 " 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"
1161 "# ifdef USEDIFFUSE\n"
1162 " // calculate directional shading\n"
1163 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1165 " // calculate directionless shading\n"
1166 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1170 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1171 "#if !showshadowmap\n"
1172 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1176 "# ifdef USECUBEFILTER\n"
1177 " // apply light cubemap filter\n"
1178 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1179 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1181 "#endif // MODE_LIGHTSOURCE\n"
1186 "#ifdef MODE_LIGHTDIRECTION\n"
1187 " // directional model lighting\n"
1188 "# ifdef USEDIFFUSE\n"
1189 " // get the light normal\n"
1190 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1192 "# ifdef USESPECULAR\n"
1193 " // calculate directional shading\n"
1194 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1195 "# ifdef USEEXACTSPECULARMATH\n"
1196 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1198 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1199 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1202 "# ifdef USEDIFFUSE\n"
1204 " // calculate directional shading\n"
1205 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1207 " color.rgb *= AmbientColor;\n"
1210 "#endif // MODE_LIGHTDIRECTION\n"
1215 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1216 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1218 " // get the light normal\n"
1219 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1220 " myhalf3 diffusenormal;\n"
1221 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1222 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1223 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1224 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1225 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1226 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1227 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1228 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1229 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1230 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1231 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1232 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1233 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1234 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1235 "# ifdef USESPECULAR\n"
1236 "# ifdef USEEXACTSPECULARMATH\n"
1237 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1239 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1240 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1244 " // apply lightmap color\n"
1245 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1246 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1251 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1252 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1254 " // get the light normal\n"
1255 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1256 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1257 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1258 "# ifdef USESPECULAR\n"
1259 "# ifdef USEEXACTSPECULARMATH\n"
1260 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1262 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1263 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1267 " // apply lightmap color\n"
1268 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1269 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1274 "#ifdef MODE_LIGHTMAP\n"
1275 " // apply lightmap color\n"
1276 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1277 "#endif // MODE_LIGHTMAP\n"
1282 "#ifdef MODE_VERTEXCOLOR\n"
1283 " // apply lightmap color\n"
1284 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1285 "#endif // MODE_VERTEXCOLOR\n"
1290 "#ifdef MODE_FLATCOLOR\n"
1291 "#endif // MODE_FLATCOLOR\n"
1299 " color *= TintColor;\n"
1302 "#ifdef USEVERTEXTEXTUREBLEND\n"
1303 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1305 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1309 "#ifdef USECONTRASTBOOST\n"
1310 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1313 " color.rgb *= SceneBrightness;\n"
1315 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1317 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1320 " // 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"
1321 "#ifdef USEREFLECTION\n"
1322 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1323 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1324 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1325 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1328 " gl_FragColor = vec4(color);\n"
1330 "#if showshadowmap\n"
1331 "# ifdef USESHADOWMAPRECT\n"
1332 "# if useshadowsamplerrect\n"
1333 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1335 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1339 "# ifdef USESHADOWMAP2D\n"
1340 "# if useshadowsampler2d\n"
1341 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1343 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1347 "# ifdef USESHADOWMAPCUBE\n"
1348 "# if useshadowsamplercube\n"
1349 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1351 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1356 "#endif // !MODE_REFRACTION\n"
1357 "#endif // !MODE_WATER\n"
1359 "#endif // FRAGMENT_SHADER\n"
1361 "#endif // !MODE_GENERIC\n"
1362 "#endif // !MODE_POSTPROCESS\n"
1363 "#endif // !MODE_SHOWDEPTH\n"
1364 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1367 typedef struct shaderpermutationinfo_s
1369 const char *pretext;
1372 shaderpermutationinfo_t;
1374 typedef struct shadermodeinfo_s
1376 const char *vertexfilename;
1377 const char *geometryfilename;
1378 const char *fragmentfilename;
1379 const char *pretext;
1384 typedef enum shaderpermutation_e
1386 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1387 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1388 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1389 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1390 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1391 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1392 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1393 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1394 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1395 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1396 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1397 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1398 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1399 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1400 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1401 SHADERPERMUTATION_SHADOWMAPRECT = 1<<15, ///< (lightsource) use shadowmap rectangle texture as light filter
1402 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<16, ///< (lightsource) use shadowmap cubemap texture as light filter
1403 SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1404 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1405 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1407 shaderpermutation_t;
1409 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1410 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1412 {"#define USEDIFFUSE\n", " diffuse"},
1413 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1414 {"#define USECOLORMAPPING\n", " colormapping"},
1415 {"#define USECONTRASTBOOST\n", " contrastboost"},
1416 {"#define USEFOG\n", " fog"},
1417 {"#define USECUBEFILTER\n", " cubefilter"},
1418 {"#define USEGLOW\n", " glow"},
1419 {"#define USESPECULAR\n", " specular"},
1420 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1421 {"#define USEREFLECTION\n", " reflection"},
1422 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1423 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1424 {"#define USEGAMMARAMPS\n", " gammaramps"},
1425 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1426 {"#define USESATURATION\n", " saturation"},
1427 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1428 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1429 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1432 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1433 typedef enum shadermode_e
1435 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1436 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1437 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1438 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1439 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1440 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1441 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1442 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1443 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1444 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1445 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1446 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1447 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1452 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1453 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1455 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1456 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1457 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1458 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1459 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1460 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1461 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1462 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1463 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1464 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1465 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1466 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1467 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1470 typedef struct r_glsl_permutation_s
1472 /// indicates if we have tried compiling this permutation already
1474 /// 0 if compilation failed
1476 /// locations of detected uniforms in program object, or -1 if not found
1477 int loc_Texture_First;
1478 int loc_Texture_Second;
1479 int loc_Texture_GammaRamps;
1480 int loc_Texture_Normal;
1481 int loc_Texture_Color;
1482 int loc_Texture_Gloss;
1483 int loc_Texture_Glow;
1484 int loc_Texture_SecondaryNormal;
1485 int loc_Texture_SecondaryColor;
1486 int loc_Texture_SecondaryGloss;
1487 int loc_Texture_SecondaryGlow;
1488 int loc_Texture_Pants;
1489 int loc_Texture_Shirt;
1490 int loc_Texture_FogMask;
1491 int loc_Texture_Lightmap;
1492 int loc_Texture_Deluxemap;
1493 int loc_Texture_Attenuation;
1494 int loc_Texture_Cube;
1495 int loc_Texture_Refraction;
1496 int loc_Texture_Reflection;
1497 int loc_Texture_ShadowMapRect;
1498 int loc_Texture_ShadowMapCube;
1499 int loc_Texture_ShadowMap2D;
1501 int loc_LightPosition;
1502 int loc_EyePosition;
1503 int loc_Color_Pants;
1504 int loc_Color_Shirt;
1505 int loc_FogRangeRecip;
1506 int loc_AmbientScale;
1507 int loc_DiffuseScale;
1508 int loc_SpecularScale;
1509 int loc_SpecularPower;
1511 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1512 int loc_OffsetMapping_Scale;
1514 int loc_AmbientColor;
1515 int loc_DiffuseColor;
1516 int loc_SpecularColor;
1518 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1519 int loc_GammaCoeff; ///< 1 / gamma
1520 int loc_DistortScaleRefractReflect;
1521 int loc_ScreenScaleRefractReflect;
1522 int loc_ScreenCenterRefractReflect;
1523 int loc_RefractColor;
1524 int loc_ReflectColor;
1525 int loc_ReflectFactor;
1526 int loc_ReflectOffset;
1534 int loc_ShadowMap_Bias;
1535 int loc_ShadowMap_TextureScale;
1536 int loc_ShadowMap_Parameters;
1538 r_glsl_permutation_t;
1540 /// information about each possible shader permutation
1541 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1542 /// currently selected permutation
1543 r_glsl_permutation_t *r_glsl_permutation;
1545 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1548 if (!filename || !filename[0])
1550 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1553 if (printfromdisknotice)
1554 Con_DPrint("from disk... ");
1555 return shaderstring;
1557 else if (!strcmp(filename, "glsl/default.glsl"))
1559 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1560 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1562 return shaderstring;
1565 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1568 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1569 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1570 int vertstrings_count = 0;
1571 int geomstrings_count = 0;
1572 int fragstrings_count = 0;
1573 char *vertexstring, *geometrystring, *fragmentstring;
1574 const char *vertstrings_list[32+3];
1575 const char *geomstrings_list[32+3];
1576 const char *fragstrings_list[32+3];
1577 char permutationname[256];
1584 permutationname[0] = 0;
1585 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1586 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1587 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1589 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1591 // the first pretext is which type of shader to compile as
1592 // (later these will all be bound together as a program object)
1593 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1594 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1595 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1597 // the second pretext is the mode (for example a light source)
1598 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1599 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1600 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1601 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1603 // now add all the permutation pretexts
1604 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1606 if (permutation & (1<<i))
1608 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1609 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1610 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1611 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1615 // keep line numbers correct
1616 vertstrings_list[vertstrings_count++] = "\n";
1617 geomstrings_list[geomstrings_count++] = "\n";
1618 fragstrings_list[fragstrings_count++] = "\n";
1622 // now append the shader text itself
1623 vertstrings_list[vertstrings_count++] = vertexstring;
1624 geomstrings_list[geomstrings_count++] = geometrystring;
1625 fragstrings_list[fragstrings_count++] = fragmentstring;
1627 // if any sources were NULL, clear the respective list
1629 vertstrings_count = 0;
1630 if (!geometrystring)
1631 geomstrings_count = 0;
1632 if (!fragmentstring)
1633 fragstrings_count = 0;
1635 // compile the shader program
1636 if (vertstrings_count + geomstrings_count + fragstrings_count)
1637 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1641 qglUseProgramObjectARB(p->program);CHECKGLERROR
1642 // look up all the uniform variable names we care about, so we don't
1643 // have to look them up every time we set them
1644 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1645 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1646 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1647 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1648 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1649 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1650 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1651 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1652 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1653 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1654 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1655 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1656 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1657 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1658 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1659 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1660 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1661 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1662 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1663 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1664 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1665 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1666 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1667 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1668 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1669 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1670 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1671 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1672 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1673 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1674 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1675 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1676 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1677 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1678 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1679 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1680 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1681 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1682 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1683 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1684 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1685 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1686 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1687 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1688 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1689 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1690 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1691 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1692 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1693 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1694 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1695 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1696 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1697 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1698 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1699 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1700 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1701 p->loc_ShadowMap_Bias = qglGetUniformLocationARB(p->program, "ShadowMap_Bias");
1702 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1703 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1704 // initialize the samplers to refer to the texture units we use
1705 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1706 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1707 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1708 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1709 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1710 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1711 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1712 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1713 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1714 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1715 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1716 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1717 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1718 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1719 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1720 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1721 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1722 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1723 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1724 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1725 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1726 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1727 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1729 if (developer.integer)
1730 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1733 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1737 Mem_Free(vertexstring);
1739 Mem_Free(geometrystring);
1741 Mem_Free(fragmentstring);
1744 void R_GLSL_Restart_f(void)
1747 unsigned int permutation;
1748 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1749 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1750 if (r_glsl_permutations[mode][permutation].program)
1751 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1752 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1755 void R_GLSL_DumpShader_f(void)
1759 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1762 Con_Printf("failed to write to glsl/default.glsl\n");
1766 FS_Print(file, "// The engine may define the following macros:\n");
1767 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1768 for (i = 0;i < SHADERMODE_COUNT;i++)
1769 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1770 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1771 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1772 FS_Print(file, "\n");
1773 FS_Print(file, builtinshaderstring);
1776 Con_Printf("glsl/default.glsl written\n");
1779 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1781 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1782 if (r_glsl_permutation != perm)
1784 r_glsl_permutation = perm;
1785 if (!r_glsl_permutation->program)
1787 if (!r_glsl_permutation->compiled)
1788 R_GLSL_CompilePermutation(mode, permutation);
1789 if (!r_glsl_permutation->program)
1791 // remove features until we find a valid permutation
1793 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1795 // reduce i more quickly whenever it would not remove any bits
1796 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1797 if (!(permutation & j))
1800 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1801 if (!r_glsl_permutation->compiled)
1802 R_GLSL_CompilePermutation(mode, permutation);
1803 if (r_glsl_permutation->program)
1806 if (i >= SHADERPERMUTATION_COUNT)
1808 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");
1809 Cvar_SetValueQuick(&r_glsl, 0);
1810 R_GLSL_Restart_f(); // unload shaders
1811 return; // no bit left to clear
1816 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1820 void R_SetupGenericShader(qboolean usetexture)
1822 if (gl_support_fragment_shader)
1824 if (r_glsl.integer && r_glsl_usegeneric.integer)
1825 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1826 else if (r_glsl_permutation)
1828 r_glsl_permutation = NULL;
1829 qglUseProgramObjectARB(0);CHECKGLERROR
1834 void R_SetupGenericTwoTextureShader(int texturemode)
1836 if (gl_support_fragment_shader)
1838 if (r_glsl.integer && r_glsl_usegeneric.integer)
1839 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))));
1840 else if (r_glsl_permutation)
1842 r_glsl_permutation = NULL;
1843 qglUseProgramObjectARB(0);CHECKGLERROR
1846 if (!r_glsl_permutation)
1848 if (texturemode == GL_DECAL && gl_combine.integer)
1849 texturemode = GL_INTERPOLATE_ARB;
1850 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1854 void R_SetupDepthOrShadowShader(void)
1856 if (gl_support_fragment_shader)
1858 if (r_glsl.integer && r_glsl_usegeneric.integer)
1859 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1860 else if (r_glsl_permutation)
1862 r_glsl_permutation = NULL;
1863 qglUseProgramObjectARB(0);CHECKGLERROR
1868 void R_SetupShowDepthShader(void)
1870 if (gl_support_fragment_shader)
1872 if (r_glsl.integer && r_glsl_usegeneric.integer)
1873 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1874 else if (r_glsl_permutation)
1876 r_glsl_permutation = NULL;
1877 qglUseProgramObjectARB(0);CHECKGLERROR
1882 extern rtexture_t *r_shadow_attenuationgradienttexture;
1883 extern rtexture_t *r_shadow_attenuation2dtexture;
1884 extern rtexture_t *r_shadow_attenuation3dtexture;
1885 extern qboolean r_shadow_usingshadowmaprect;
1886 extern qboolean r_shadow_usingshadowmapcube;
1887 extern qboolean r_shadow_usingshadowmap2d;
1888 extern float r_shadow_shadowmap_bias;
1889 extern float r_shadow_shadowmap_texturescale[2];
1890 extern float r_shadow_shadowmap_parameters[4];
1891 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1893 // select a permutation of the lighting shader appropriate to this
1894 // combination of texture, entity, light source, and fogging, only use the
1895 // minimum features necessary to avoid wasting rendering time in the
1896 // fragment shader on features that are not being used
1897 unsigned int permutation = 0;
1898 unsigned int mode = 0;
1899 // TODO: implement geometry-shader based shadow volumes someday
1900 if (r_glsl_offsetmapping.integer)
1902 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1903 if (r_glsl_offsetmapping_reliefmapping.integer)
1904 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1906 if (rsurfacepass == RSURFPASS_BACKGROUND)
1908 // distorted background
1909 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1910 mode = SHADERMODE_WATER;
1912 mode = SHADERMODE_REFRACTION;
1914 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1917 mode = SHADERMODE_LIGHTSOURCE;
1918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1919 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1920 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1921 permutation |= SHADERPERMUTATION_CUBEFILTER;
1922 if (diffusescale > 0)
1923 permutation |= SHADERPERMUTATION_DIFFUSE;
1924 if (specularscale > 0)
1925 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1926 if (r_refdef.fogenabled)
1927 permutation |= SHADERPERMUTATION_FOG;
1928 if (rsurface.texture->colormapping)
1929 permutation |= SHADERPERMUTATION_COLORMAPPING;
1930 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1931 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1932 if (r_shadow_usingshadowmaprect)
1933 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
1934 if (r_shadow_usingshadowmapcube)
1935 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
1936 if (r_shadow_usingshadowmap2d)
1937 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1939 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1941 // unshaded geometry (fullbright or ambient model lighting)
1942 mode = SHADERMODE_FLATCOLOR;
1943 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1944 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1945 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1946 permutation |= SHADERPERMUTATION_GLOW;
1947 if (r_refdef.fogenabled)
1948 permutation |= SHADERPERMUTATION_FOG;
1949 if (rsurface.texture->colormapping)
1950 permutation |= SHADERPERMUTATION_COLORMAPPING;
1951 if (r_glsl_offsetmapping.integer)
1953 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1954 if (r_glsl_offsetmapping_reliefmapping.integer)
1955 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1957 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1958 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1959 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1960 permutation |= SHADERPERMUTATION_REFLECTION;
1962 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1964 // directional model lighting
1965 mode = SHADERMODE_LIGHTDIRECTION;
1966 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1967 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1968 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1969 permutation |= SHADERPERMUTATION_GLOW;
1970 permutation |= SHADERPERMUTATION_DIFFUSE;
1971 if (specularscale > 0)
1972 permutation |= SHADERPERMUTATION_SPECULAR;
1973 if (r_refdef.fogenabled)
1974 permutation |= SHADERPERMUTATION_FOG;
1975 if (rsurface.texture->colormapping)
1976 permutation |= SHADERPERMUTATION_COLORMAPPING;
1977 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1978 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1979 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1980 permutation |= SHADERPERMUTATION_REFLECTION;
1982 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1984 // ambient model lighting
1985 mode = SHADERMODE_LIGHTDIRECTION;
1986 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1987 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1988 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1989 permutation |= SHADERPERMUTATION_GLOW;
1990 if (r_refdef.fogenabled)
1991 permutation |= SHADERPERMUTATION_FOG;
1992 if (rsurface.texture->colormapping)
1993 permutation |= SHADERPERMUTATION_COLORMAPPING;
1994 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1995 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1997 permutation |= SHADERPERMUTATION_REFLECTION;
2002 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2004 // deluxemapping (light direction texture)
2005 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2006 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2008 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2009 permutation |= SHADERPERMUTATION_DIFFUSE;
2010 if (specularscale > 0)
2011 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2013 else if (r_glsl_deluxemapping.integer >= 2)
2015 // fake deluxemapping (uniform light direction in tangentspace)
2016 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2017 permutation |= SHADERPERMUTATION_DIFFUSE;
2018 if (specularscale > 0)
2019 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2021 else if (rsurface.uselightmaptexture)
2023 // ordinary lightmapping (q1bsp, q3bsp)
2024 mode = SHADERMODE_LIGHTMAP;
2028 // ordinary vertex coloring (q3bsp)
2029 mode = SHADERMODE_VERTEXCOLOR;
2031 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2032 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2033 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2034 permutation |= SHADERPERMUTATION_GLOW;
2035 if (r_refdef.fogenabled)
2036 permutation |= SHADERPERMUTATION_FOG;
2037 if (rsurface.texture->colormapping)
2038 permutation |= SHADERPERMUTATION_COLORMAPPING;
2039 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
2040 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
2041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2042 permutation |= SHADERPERMUTATION_REFLECTION;
2044 if(permutation & SHADERPERMUTATION_SPECULAR)
2045 if(r_shadow_glossexact.integer)
2046 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2047 R_SetupShader_SetPermutation(mode, permutation);
2048 if (mode == SHADERMODE_LIGHTSOURCE)
2050 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2051 if (permutation & SHADERPERMUTATION_DIFFUSE)
2053 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2054 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2055 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2056 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2060 // ambient only is simpler
2061 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]);
2062 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2063 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2064 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2066 // additive passes are only darkened by fog, not tinted
2067 if (r_glsl_permutation->loc_FogColor >= 0)
2068 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2069 if (r_glsl_permutation->loc_ShadowMap_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_ShadowMap_Bias, r_shadow_shadowmap_bias);
2070 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2071 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2075 if (mode == SHADERMODE_LIGHTDIRECTION)
2077 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);
2078 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);
2079 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);
2080 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]);
2084 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2085 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2086 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2088 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]);
2089 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2090 // additive passes are only darkened by fog, not tinted
2091 if (r_glsl_permutation->loc_FogColor >= 0)
2093 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2094 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2096 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2098 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);
2099 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]);
2100 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]);
2101 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2102 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2103 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2104 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2106 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
2108 // The formula used is actually:
2109 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
2110 // color.rgb *= SceneBrightness;
2112 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
2113 // and do [[calculations]] here in the engine
2114 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
2115 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
2118 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2119 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2120 if (r_glsl_permutation->loc_Color_Pants >= 0)
2122 if (rsurface.texture->currentskinframe->pants)
2123 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2125 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2127 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2129 if (rsurface.texture->currentskinframe->shirt)
2130 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2132 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2134 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2135 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2137 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2141 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2143 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2147 #define SKINFRAME_HASH 1024
2151 int loadsequence; // incremented each level change
2152 memexpandablearray_t array;
2153 skinframe_t *hash[SKINFRAME_HASH];
2156 r_skinframe_t r_skinframe;
2158 void R_SkinFrame_PrepareForPurge(void)
2160 r_skinframe.loadsequence++;
2161 // wrap it without hitting zero
2162 if (r_skinframe.loadsequence >= 200)
2163 r_skinframe.loadsequence = 1;
2166 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2170 // mark the skinframe as used for the purging code
2171 skinframe->loadsequence = r_skinframe.loadsequence;
2174 void R_SkinFrame_Purge(void)
2178 for (i = 0;i < SKINFRAME_HASH;i++)
2180 for (s = r_skinframe.hash[i];s;s = s->next)
2182 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2184 if (s->merged == s->base)
2186 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2187 R_PurgeTexture(s->stain );s->stain = NULL;
2188 R_PurgeTexture(s->merged);s->merged = NULL;
2189 R_PurgeTexture(s->base );s->base = NULL;
2190 R_PurgeTexture(s->pants );s->pants = NULL;
2191 R_PurgeTexture(s->shirt );s->shirt = NULL;
2192 R_PurgeTexture(s->nmap );s->nmap = NULL;
2193 R_PurgeTexture(s->gloss );s->gloss = NULL;
2194 R_PurgeTexture(s->glow );s->glow = NULL;
2195 R_PurgeTexture(s->fog );s->fog = NULL;
2196 s->loadsequence = 0;
2202 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2204 char basename[MAX_QPATH];
2206 Image_StripImageExtension(name, basename, sizeof(basename));
2208 if( last == NULL ) {
2210 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2211 item = r_skinframe.hash[hashindex];
2216 // linearly search through the hash bucket
2217 for( ; item ; item = item->next ) {
2218 if( !strcmp( item->basename, basename ) ) {
2225 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2229 char basename[MAX_QPATH];
2231 Image_StripImageExtension(name, basename, sizeof(basename));
2233 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2234 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2235 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2239 rtexture_t *dyntexture;
2240 // check whether its a dynamic texture
2241 dyntexture = CL_GetDynTexture( basename );
2242 if (!add && !dyntexture)
2244 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2245 memset(item, 0, sizeof(*item));
2246 strlcpy(item->basename, basename, sizeof(item->basename));
2247 item->base = dyntexture; // either NULL or dyntexture handle
2248 item->textureflags = textureflags;
2249 item->comparewidth = comparewidth;
2250 item->compareheight = compareheight;
2251 item->comparecrc = comparecrc;
2252 item->next = r_skinframe.hash[hashindex];
2253 r_skinframe.hash[hashindex] = item;
2255 else if( item->base == NULL )
2257 rtexture_t *dyntexture;
2258 // check whether its a dynamic texture
2259 // 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]
2260 dyntexture = CL_GetDynTexture( basename );
2261 item->base = dyntexture; // either NULL or dyntexture handle
2264 R_SkinFrame_MarkUsed(item);
2268 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2270 unsigned long long avgcolor[5], wsum; \
2278 for(pix = 0; pix < cnt; ++pix) \
2281 for(comp = 0; comp < 3; ++comp) \
2283 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2286 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2288 for(comp = 0; comp < 3; ++comp) \
2289 avgcolor[comp] += getpixel * w; \
2292 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2293 avgcolor[4] += getpixel; \
2295 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2297 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2298 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2299 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2300 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2303 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2305 // FIXME: it should be possible to disable loading various layers using
2306 // cvars, to prevent wasted loading time and memory usage if the user does
2308 qboolean loadnormalmap = true;
2309 qboolean loadgloss = true;
2310 qboolean loadpantsandshirt = true;
2311 qboolean loadglow = true;
2313 unsigned char *pixels;
2314 unsigned char *bumppixels;
2315 unsigned char *basepixels = NULL;
2316 int basepixels_width;
2317 int basepixels_height;
2318 skinframe_t *skinframe;
2322 if (cls.state == ca_dedicated)
2325 // return an existing skinframe if already loaded
2326 // if loading of the first image fails, don't make a new skinframe as it
2327 // would cause all future lookups of this to be missing
2328 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2329 if (skinframe && skinframe->base)
2332 basepixels = loadimagepixelsbgra(name, complain, true);
2333 if (basepixels == NULL)
2336 if (developer_loading.integer)
2337 Con_Printf("loading skin \"%s\"\n", name);
2339 // we've got some pixels to store, so really allocate this new texture now
2341 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2342 skinframe->stain = NULL;
2343 skinframe->merged = NULL;
2344 skinframe->base = r_texture_notexture;
2345 skinframe->pants = NULL;
2346 skinframe->shirt = NULL;
2347 skinframe->nmap = r_texture_blanknormalmap;
2348 skinframe->gloss = NULL;
2349 skinframe->glow = NULL;
2350 skinframe->fog = NULL;
2352 basepixels_width = image_width;
2353 basepixels_height = image_height;
2354 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);
2356 if (textureflags & TEXF_ALPHA)
2358 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2359 if (basepixels[j] < 255)
2361 if (j < basepixels_width * basepixels_height * 4)
2363 // has transparent pixels
2365 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2366 for (j = 0;j < image_width * image_height * 4;j += 4)
2371 pixels[j+3] = basepixels[j+3];
2373 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);
2378 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2379 //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]);
2381 // _norm is the name used by tenebrae and has been adopted as standard
2384 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2386 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);
2390 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2392 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2393 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2394 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);
2396 Mem_Free(bumppixels);
2398 else if (r_shadow_bumpscale_basetexture.value > 0)
2400 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2401 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2402 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);
2406 // _luma is supported for tenebrae compatibility
2407 // (I think it's a very stupid name, but oh well)
2408 // _glow is the preferred name
2409 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;}
2410 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;}
2411 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;}
2412 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;}
2415 Mem_Free(basepixels);
2420 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2423 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2426 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)
2431 for (i = 0;i < width*height;i++)
2432 if (((unsigned char *)&palette[in[i]])[3] > 0)
2434 if (i == width*height)
2437 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2440 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2441 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2444 unsigned char *temp1, *temp2;
2445 skinframe_t *skinframe;
2447 if (cls.state == ca_dedicated)
2450 // if already loaded just return it, otherwise make a new skinframe
2451 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2452 if (skinframe && skinframe->base)
2455 skinframe->stain = NULL;
2456 skinframe->merged = NULL;
2457 skinframe->base = r_texture_notexture;
2458 skinframe->pants = NULL;
2459 skinframe->shirt = NULL;
2460 skinframe->nmap = r_texture_blanknormalmap;
2461 skinframe->gloss = NULL;
2462 skinframe->glow = NULL;
2463 skinframe->fog = NULL;
2465 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2469 if (developer_loading.integer)
2470 Con_Printf("loading 32bit skin \"%s\"\n", name);
2472 if (r_shadow_bumpscale_basetexture.value > 0)
2474 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2475 temp2 = temp1 + width * height * 4;
2476 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2477 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2480 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2481 if (textureflags & TEXF_ALPHA)
2483 for (i = 3;i < width * height * 4;i += 4)
2484 if (skindata[i] < 255)
2486 if (i < width * height * 4)
2488 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2489 memcpy(fogpixels, skindata, width * height * 4);
2490 for (i = 0;i < width * height * 4;i += 4)
2491 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2492 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2493 Mem_Free(fogpixels);
2497 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2498 //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]);
2503 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2506 unsigned char *temp1, *temp2;
2507 unsigned int *palette;
2508 skinframe_t *skinframe;
2510 if (cls.state == ca_dedicated)
2513 // if already loaded just return it, otherwise make a new skinframe
2514 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2515 if (skinframe && skinframe->base)
2518 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2520 skinframe->stain = NULL;
2521 skinframe->merged = NULL;
2522 skinframe->base = r_texture_notexture;
2523 skinframe->pants = NULL;
2524 skinframe->shirt = NULL;
2525 skinframe->nmap = r_texture_blanknormalmap;
2526 skinframe->gloss = NULL;
2527 skinframe->glow = NULL;
2528 skinframe->fog = NULL;
2530 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2534 if (developer_loading.integer)
2535 Con_Printf("loading quake skin \"%s\"\n", name);
2537 if (r_shadow_bumpscale_basetexture.value > 0)
2539 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2540 temp2 = temp1 + width * height * 4;
2541 // use either a custom palette or the quake palette
2542 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2543 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2544 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2547 // use either a custom palette, or the quake palette
2548 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2549 if (loadglowtexture)
2550 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2551 if (loadpantsandshirt)
2553 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2554 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2556 if (skinframe->pants || skinframe->shirt)
2557 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
2558 if (textureflags & TEXF_ALPHA)
2560 for (i = 0;i < width * height;i++)
2561 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2563 if (i < width * height)
2564 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2567 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2568 //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]);
2573 skinframe_t *R_SkinFrame_LoadMissing(void)
2575 skinframe_t *skinframe;
2577 if (cls.state == ca_dedicated)
2580 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2581 skinframe->stain = NULL;
2582 skinframe->merged = NULL;
2583 skinframe->base = r_texture_notexture;
2584 skinframe->pants = NULL;
2585 skinframe->shirt = NULL;
2586 skinframe->nmap = r_texture_blanknormalmap;
2587 skinframe->gloss = NULL;
2588 skinframe->glow = NULL;
2589 skinframe->fog = NULL;
2591 skinframe->avgcolor[0] = rand() / RAND_MAX;
2592 skinframe->avgcolor[1] = rand() / RAND_MAX;
2593 skinframe->avgcolor[2] = rand() / RAND_MAX;
2594 skinframe->avgcolor[3] = 1;
2599 void gl_main_start(void)
2603 memset(r_queries, 0, sizeof(r_queries));
2605 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2606 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2608 // set up r_skinframe loading system for textures
2609 memset(&r_skinframe, 0, sizeof(r_skinframe));
2610 r_skinframe.loadsequence = 1;
2611 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2613 r_main_texturepool = R_AllocTexturePool();
2614 R_BuildBlankTextures();
2616 if (gl_texturecubemap)
2619 R_BuildNormalizationCube();
2621 r_texture_fogattenuation = NULL;
2622 r_texture_gammaramps = NULL;
2623 //r_texture_fogintensity = NULL;
2624 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2625 memset(&r_waterstate, 0, sizeof(r_waterstate));
2626 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2627 memset(&r_svbsp, 0, sizeof (r_svbsp));
2629 r_refdef.fogmasktable_density = 0;
2632 extern rtexture_t *loadingscreentexture;
2633 void gl_main_shutdown(void)
2636 qglDeleteQueriesARB(r_maxqueries, r_queries);
2640 memset(r_queries, 0, sizeof(r_queries));
2642 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2643 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2645 // clear out the r_skinframe state
2646 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2647 memset(&r_skinframe, 0, sizeof(r_skinframe));
2650 Mem_Free(r_svbsp.nodes);
2651 memset(&r_svbsp, 0, sizeof (r_svbsp));
2652 R_FreeTexturePool(&r_main_texturepool);
2653 loadingscreentexture = NULL;
2654 r_texture_blanknormalmap = NULL;
2655 r_texture_white = NULL;
2656 r_texture_grey128 = NULL;
2657 r_texture_black = NULL;
2658 r_texture_whitecube = NULL;
2659 r_texture_normalizationcube = NULL;
2660 r_texture_fogattenuation = NULL;
2661 r_texture_gammaramps = NULL;
2662 //r_texture_fogintensity = NULL;
2663 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2664 memset(&r_waterstate, 0, sizeof(r_waterstate));
2668 extern void CL_ParseEntityLump(char *entitystring);
2669 void gl_main_newmap(void)
2671 // FIXME: move this code to client
2673 char *entities, entname[MAX_QPATH];
2676 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2677 l = (int)strlen(entname) - 4;
2678 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2680 memcpy(entname + l, ".ent", 5);
2681 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2683 CL_ParseEntityLump(entities);
2688 if (cl.worldmodel->brush.entities)
2689 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2693 void GL_Main_Init(void)
2695 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2697 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2698 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2699 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2700 if (gamemode == GAME_NEHAHRA)
2702 Cvar_RegisterVariable (&gl_fogenable);
2703 Cvar_RegisterVariable (&gl_fogdensity);
2704 Cvar_RegisterVariable (&gl_fogred);
2705 Cvar_RegisterVariable (&gl_foggreen);
2706 Cvar_RegisterVariable (&gl_fogblue);
2707 Cvar_RegisterVariable (&gl_fogstart);
2708 Cvar_RegisterVariable (&gl_fogend);
2709 Cvar_RegisterVariable (&gl_skyclip);
2711 Cvar_RegisterVariable(&r_motionblur);
2712 Cvar_RegisterVariable(&r_motionblur_maxblur);
2713 Cvar_RegisterVariable(&r_motionblur_bmin);
2714 Cvar_RegisterVariable(&r_motionblur_vmin);
2715 Cvar_RegisterVariable(&r_motionblur_vmax);
2716 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2717 Cvar_RegisterVariable(&r_motionblur_randomize);
2718 Cvar_RegisterVariable(&r_damageblur);
2719 Cvar_RegisterVariable(&r_animcache);
2720 Cvar_RegisterVariable(&r_depthfirst);
2721 Cvar_RegisterVariable(&r_useinfinitefarclip);
2722 Cvar_RegisterVariable(&r_nearclip);
2723 Cvar_RegisterVariable(&r_showbboxes);
2724 Cvar_RegisterVariable(&r_showsurfaces);
2725 Cvar_RegisterVariable(&r_showtris);
2726 Cvar_RegisterVariable(&r_shownormals);
2727 Cvar_RegisterVariable(&r_showlighting);
2728 Cvar_RegisterVariable(&r_showshadowvolumes);
2729 Cvar_RegisterVariable(&r_showcollisionbrushes);
2730 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2731 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2732 Cvar_RegisterVariable(&r_showdisabledepthtest);
2733 Cvar_RegisterVariable(&r_drawportals);
2734 Cvar_RegisterVariable(&r_drawentities);
2735 Cvar_RegisterVariable(&r_cullentities_trace);
2736 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2737 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2738 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2739 Cvar_RegisterVariable(&r_drawviewmodel);
2740 Cvar_RegisterVariable(&r_speeds);
2741 Cvar_RegisterVariable(&r_fullbrights);
2742 Cvar_RegisterVariable(&r_wateralpha);
2743 Cvar_RegisterVariable(&r_dynamic);
2744 Cvar_RegisterVariable(&r_fullbright);
2745 Cvar_RegisterVariable(&r_shadows);
2746 Cvar_RegisterVariable(&r_shadows_darken);
2747 Cvar_RegisterVariable(&r_shadows_drawafterrtlightning);
2748 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2749 Cvar_RegisterVariable(&r_shadows_throwdistance);
2750 Cvar_RegisterVariable(&r_shadows_throwdirection);
2751 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2752 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2753 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2754 Cvar_RegisterVariable(&r_fog_exp2);
2755 Cvar_RegisterVariable(&r_drawfog);
2756 Cvar_RegisterVariable(&r_textureunits);
2757 Cvar_RegisterVariable(&r_glsl);
2758 Cvar_RegisterVariable(&r_glsl_contrastboost);
2759 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2760 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2761 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2762 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2763 Cvar_RegisterVariable(&r_glsl_postprocess);
2764 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2765 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2766 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2767 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2768 Cvar_RegisterVariable(&r_glsl_usegeneric);
2769 Cvar_RegisterVariable(&r_water);
2770 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2771 Cvar_RegisterVariable(&r_water_clippingplanebias);
2772 Cvar_RegisterVariable(&r_water_refractdistort);
2773 Cvar_RegisterVariable(&r_water_reflectdistort);
2774 Cvar_RegisterVariable(&r_lerpsprites);
2775 Cvar_RegisterVariable(&r_lerpmodels);
2776 Cvar_RegisterVariable(&r_lerplightstyles);
2777 Cvar_RegisterVariable(&r_waterscroll);
2778 Cvar_RegisterVariable(&r_bloom);
2779 Cvar_RegisterVariable(&r_bloom_colorscale);
2780 Cvar_RegisterVariable(&r_bloom_brighten);
2781 Cvar_RegisterVariable(&r_bloom_blur);
2782 Cvar_RegisterVariable(&r_bloom_resolution);
2783 Cvar_RegisterVariable(&r_bloom_colorexponent);
2784 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2785 Cvar_RegisterVariable(&r_hdr);
2786 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2787 Cvar_RegisterVariable(&r_hdr_glowintensity);
2788 Cvar_RegisterVariable(&r_hdr_range);
2789 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2790 Cvar_RegisterVariable(&developer_texturelogging);
2791 Cvar_RegisterVariable(&gl_lightmaps);
2792 Cvar_RegisterVariable(&r_test);
2793 Cvar_RegisterVariable(&r_batchmode);
2794 Cvar_RegisterVariable(&r_glsl_saturation);
2795 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2796 Cvar_SetValue("r_fullbrights", 0);
2797 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2799 Cvar_RegisterVariable(&r_track_sprites);
2800 Cvar_RegisterVariable(&r_track_sprites_flags);
2801 Cvar_RegisterVariable(&r_track_sprites_scalew);
2802 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2805 extern void R_Textures_Init(void);
2806 extern void GL_Draw_Init(void);
2807 extern void GL_Main_Init(void);
2808 extern void R_Shadow_Init(void);
2809 extern void R_Sky_Init(void);
2810 extern void GL_Surf_Init(void);
2811 extern void R_Particles_Init(void);
2812 extern void R_Explosion_Init(void);
2813 extern void gl_backend_init(void);
2814 extern void Sbar_Init(void);
2815 extern void R_LightningBeams_Init(void);
2816 extern void Mod_RenderInit(void);
2818 void Render_Init(void)
2830 R_LightningBeams_Init();
2839 extern char *ENGINE_EXTENSIONS;
2842 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2843 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2844 gl_version = (const char *)qglGetString(GL_VERSION);
2845 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2849 if (!gl_platformextensions)
2850 gl_platformextensions = "";
2852 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2853 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2854 Con_Printf("GL_VERSION: %s\n", gl_version);
2855 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2856 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2858 VID_CheckExtensions();
2860 // LordHavoc: report supported extensions
2861 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2863 // clear to black (loading plaque will be seen over this)
2865 qglClearColor(0,0,0,1);CHECKGLERROR
2866 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2869 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2873 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2875 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2878 p = r_refdef.view.frustum + i;
2883 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2887 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2891 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2895 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2899 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2903 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2907 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2911 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2919 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2923 for (i = 0;i < numplanes;i++)
2930 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2934 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2938 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2942 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2946 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2950 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2954 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2958 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2966 //==================================================================================
2968 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2971 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2972 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2973 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2976 typedef struct r_animcache_entity_s
2983 qboolean wantnormals;
2984 qboolean wanttangents;
2986 r_animcache_entity_t;
2988 typedef struct r_animcache_s
2990 r_animcache_entity_t entity[MAX_EDICTS*2];
2996 static r_animcache_t r_animcachestate;
2998 void R_AnimCache_Free(void)
3001 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3003 r_animcachestate.entity[idx].maxvertices = 0;
3004 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3005 r_animcachestate.entity[idx].vertex3f = NULL;
3006 r_animcachestate.entity[idx].normal3f = NULL;
3007 r_animcachestate.entity[idx].svector3f = NULL;
3008 r_animcachestate.entity[idx].tvector3f = NULL;
3010 r_animcachestate.currentindex = 0;
3011 r_animcachestate.maxindex = 0;
3014 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3018 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3020 if (cache->maxvertices >= numvertices)
3023 // Release existing memory
3024 if (cache->vertex3f)
3025 Mem_Free(cache->vertex3f);
3027 // Pad by 1024 verts
3028 cache->maxvertices = (numvertices + 1023) & ~1023;
3029 arraySize = cache->maxvertices * 3;
3031 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3032 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3033 r_animcachestate.entity[cacheIdx].vertex3f = base;
3034 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3035 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3036 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3038 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3041 void R_AnimCache_NewFrame(void)
3045 if (r_animcache.integer && r_drawentities.integer)
3046 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3047 else if (r_animcachestate.maxindex)
3050 r_animcachestate.currentindex = 0;
3052 for (i = 0;i < r_refdef.scene.numentities;i++)
3053 r_refdef.scene.entities[i]->animcacheindex = -1;
3056 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3058 dp_model_t *model = ent->model;
3059 r_animcache_entity_t *c;
3060 // see if it's already cached this frame
3061 if (ent->animcacheindex >= 0)
3063 // add normals/tangents if needed
3064 c = r_animcachestate.entity + ent->animcacheindex;
3066 wantnormals = false;
3067 if (c->wanttangents)
3068 wanttangents = false;
3069 if (wantnormals || wanttangents)
3070 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3074 // see if this ent is worth caching
3075 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3077 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3079 // assign it a cache entry and make sure the arrays are big enough
3080 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3081 ent->animcacheindex = r_animcachestate.currentindex++;
3082 c = r_animcachestate.entity + ent->animcacheindex;
3083 c->wantnormals = wantnormals;
3084 c->wanttangents = wanttangents;
3085 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3090 void R_AnimCache_CacheVisibleEntities(void)
3093 qboolean wantnormals;
3094 qboolean wanttangents;
3096 if (!r_animcachestate.maxindex)
3099 wantnormals = !r_showsurfaces.integer;
3100 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3102 // TODO: thread this?
3104 for (i = 0;i < r_refdef.scene.numentities;i++)
3106 if (!r_refdef.viewcache.entityvisible[i])
3108 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3112 //==================================================================================
3114 static void R_View_UpdateEntityLighting (void)
3117 entity_render_t *ent;
3118 vec3_t tempdiffusenormal;
3120 for (i = 0;i < r_refdef.scene.numentities;i++)
3122 ent = r_refdef.scene.entities[i];
3124 // skip unseen models
3125 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3129 if (ent->model && ent->model->brush.num_leafs)
3131 // TODO: use modellight for r_ambient settings on world?
3132 VectorSet(ent->modellight_ambient, 0, 0, 0);
3133 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3134 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3138 // fetch the lighting from the worldmodel data
3139 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));
3140 VectorClear(ent->modellight_diffuse);
3141 VectorClear(tempdiffusenormal);
3142 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3145 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3146 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3149 VectorSet(ent->modellight_ambient, 1, 1, 1);
3151 // move the light direction into modelspace coordinates for lighting code
3152 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3153 if(VectorLength2(ent->modellight_lightdir) == 0)
3154 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3155 VectorNormalize(ent->modellight_lightdir);
3159 static void R_View_UpdateEntityVisible (void)
3162 entity_render_t *ent;
3164 if (!r_drawentities.integer)
3167 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3168 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3170 // worldmodel can check visibility
3171 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3172 for (i = 0;i < r_refdef.scene.numentities;i++)
3174 ent = r_refdef.scene.entities[i];
3175 if (!(ent->flags & renderimask))
3176 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)))
3177 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))
3178 r_refdef.viewcache.entityvisible[i] = true;
3180 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3182 for (i = 0;i < r_refdef.scene.numentities;i++)
3184 ent = r_refdef.scene.entities[i];
3185 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3187 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))
3188 ent->last_trace_visibility = realtime;
3189 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3190 r_refdef.viewcache.entityvisible[i] = 0;
3197 // no worldmodel or it can't check visibility
3198 for (i = 0;i < r_refdef.scene.numentities;i++)
3200 ent = r_refdef.scene.entities[i];
3201 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));
3206 /// only used if skyrendermasked, and normally returns false
3207 int R_DrawBrushModelsSky (void)
3210 entity_render_t *ent;
3212 if (!r_drawentities.integer)
3216 for (i = 0;i < r_refdef.scene.numentities;i++)
3218 if (!r_refdef.viewcache.entityvisible[i])
3220 ent = r_refdef.scene.entities[i];
3221 if (!ent->model || !ent->model->DrawSky)
3223 ent->model->DrawSky(ent);
3229 static void R_DrawNoModel(entity_render_t *ent);
3230 static void R_DrawModels(void)
3233 entity_render_t *ent;
3235 if (!r_drawentities.integer)
3238 for (i = 0;i < r_refdef.scene.numentities;i++)
3240 if (!r_refdef.viewcache.entityvisible[i])
3242 ent = r_refdef.scene.entities[i];
3243 r_refdef.stats.entities++;
3244 if (ent->model && ent->model->Draw != NULL)
3245 ent->model->Draw(ent);
3251 static void R_DrawModelsDepth(void)
3254 entity_render_t *ent;
3256 if (!r_drawentities.integer)
3259 for (i = 0;i < r_refdef.scene.numentities;i++)
3261 if (!r_refdef.viewcache.entityvisible[i])
3263 ent = r_refdef.scene.entities[i];
3264 if (ent->model && ent->model->DrawDepth != NULL)
3265 ent->model->DrawDepth(ent);
3269 static void R_DrawModelsDebug(void)
3272 entity_render_t *ent;
3274 if (!r_drawentities.integer)
3277 for (i = 0;i < r_refdef.scene.numentities;i++)
3279 if (!r_refdef.viewcache.entityvisible[i])
3281 ent = r_refdef.scene.entities[i];
3282 if (ent->model && ent->model->DrawDebug != NULL)
3283 ent->model->DrawDebug(ent);
3287 static void R_DrawModelsAddWaterPlanes(void)
3290 entity_render_t *ent;
3292 if (!r_drawentities.integer)
3295 for (i = 0;i < r_refdef.scene.numentities;i++)
3297 if (!r_refdef.viewcache.entityvisible[i])
3299 ent = r_refdef.scene.entities[i];
3300 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3301 ent->model->DrawAddWaterPlanes(ent);
3305 static void R_View_SetFrustum(void)
3308 double slopex, slopey;
3309 vec3_t forward, left, up, origin;
3311 // we can't trust r_refdef.view.forward and friends in reflected scenes
3312 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3315 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3316 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3317 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3318 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3319 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3320 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3321 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3322 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3323 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3324 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3325 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3326 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3330 zNear = r_refdef.nearclip;
3331 nudge = 1.0 - 1.0 / (1<<23);
3332 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3333 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3334 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3335 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3336 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3337 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3338 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3339 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3345 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3346 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3347 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3348 r_refdef.view.frustum[0].dist = m[15] - m[12];
3350 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3351 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3352 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3353 r_refdef.view.frustum[1].dist = m[15] + m[12];
3355 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3356 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3357 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3358 r_refdef.view.frustum[2].dist = m[15] - m[13];
3360 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3361 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3362 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3363 r_refdef.view.frustum[3].dist = m[15] + m[13];
3365 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3366 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3367 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3368 r_refdef.view.frustum[4].dist = m[15] - m[14];
3370 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3371 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3372 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3373 r_refdef.view.frustum[5].dist = m[15] + m[14];
3376 if (r_refdef.view.useperspective)
3378 slopex = 1.0 / r_refdef.view.frustum_x;
3379 slopey = 1.0 / r_refdef.view.frustum_y;
3380 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3381 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3382 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3383 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3384 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3386 // Leaving those out was a mistake, those were in the old code, and they
3387 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3388 // I couldn't reproduce it after adding those normalizations. --blub
3389 VectorNormalize(r_refdef.view.frustum[0].normal);
3390 VectorNormalize(r_refdef.view.frustum[1].normal);
3391 VectorNormalize(r_refdef.view.frustum[2].normal);
3392 VectorNormalize(r_refdef.view.frustum[3].normal);
3394 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3395 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3396 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3397 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
3398 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
3400 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3401 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3402 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3403 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3404 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3408 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3409 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3410 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3411 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3412 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3413 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3414 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3415 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3416 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3417 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3419 r_refdef.view.numfrustumplanes = 5;
3421 if (r_refdef.view.useclipplane)
3423 r_refdef.view.numfrustumplanes = 6;
3424 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3427 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3428 PlaneClassify(r_refdef.view.frustum + i);
3430 // LordHavoc: note to all quake engine coders, Quake had a special case
3431 // for 90 degrees which assumed a square view (wrong), so I removed it,
3432 // Quake2 has it disabled as well.
3434 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3435 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3436 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3437 //PlaneClassify(&frustum[0]);
3439 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3440 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3441 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3442 //PlaneClassify(&frustum[1]);
3444 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3445 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3446 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3447 //PlaneClassify(&frustum[2]);
3449 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3450 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3451 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3452 //PlaneClassify(&frustum[3]);
3455 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3456 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3457 //PlaneClassify(&frustum[4]);
3460 void R_View_Update(void)
3462 R_View_SetFrustum();
3463 R_View_WorldVisibility(r_refdef.view.useclipplane);
3464 R_View_UpdateEntityVisible();
3465 R_View_UpdateEntityLighting();
3468 void R_SetupView(qboolean allowwaterclippingplane)
3470 const double *customclipplane = NULL;
3472 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3474 // LordHavoc: couldn't figure out how to make this approach the
3475 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3476 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3477 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3478 dist = r_refdef.view.clipplane.dist;
3479 plane[0] = r_refdef.view.clipplane.normal[0];
3480 plane[1] = r_refdef.view.clipplane.normal[1];
3481 plane[2] = r_refdef.view.clipplane.normal[2];
3483 customclipplane = plane;
3486 if (!r_refdef.view.useperspective)
3487 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -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, customclipplane);
3488 else if (gl_stencil && r_useinfinitefarclip.integer)
3489 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
3491 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
3492 R_SetViewport(&r_refdef.view.viewport);
3495 void R_ResetViewRendering2D(void)
3497 r_viewport_t viewport;
3500 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3501 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3502 R_SetViewport(&viewport);
3503 GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
3504 GL_Color(1, 1, 1, 1);
3505 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3506 GL_BlendFunc(GL_ONE, GL_ZERO);
3507 GL_AlphaTest(false);
3508 GL_ScissorTest(false);
3509 GL_DepthMask(false);
3510 GL_DepthRange(0, 1);
3511 GL_DepthTest(false);
3512 R_Mesh_Matrix(&identitymatrix);
3513 R_Mesh_ResetTextureState();
3514 GL_PolygonOffset(0, 0);
3515 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3516 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3517 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3518 qglStencilMask(~0);CHECKGLERROR
3519 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3520 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3521 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3522 R_SetupGenericShader(true);
3525 void R_ResetViewRendering3D(void)
3529 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3530 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3532 GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
3533 GL_Color(1, 1, 1, 1);
3534 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3535 GL_BlendFunc(GL_ONE, GL_ZERO);
3536 GL_AlphaTest(false);
3537 GL_ScissorTest(true);
3539 GL_DepthRange(0, 1);
3541 R_Mesh_Matrix(&identitymatrix);
3542 R_Mesh_ResetTextureState();
3543 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3544 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3545 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3546 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3547 qglStencilMask(~0);CHECKGLERROR
3548 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3549 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3550 GL_CullFace(r_refdef.view.cullface_back);
3551 R_SetupGenericShader(true);
3554 void R_RenderScene(void);
3555 void R_RenderWaterPlanes(void);
3557 static void R_Water_StartFrame(void)
3560 int waterwidth, waterheight, texturewidth, textureheight;
3561 r_waterstate_waterplane_t *p;
3563 // set waterwidth and waterheight to the water resolution that will be
3564 // used (often less than the screen resolution for faster rendering)
3565 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3566 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3568 // calculate desired texture sizes
3569 // can't use water if the card does not support the texture size
3570 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3571 texturewidth = textureheight = waterwidth = waterheight = 0;
3572 else if (gl_support_arb_texture_non_power_of_two)
3574 texturewidth = waterwidth;
3575 textureheight = waterheight;
3579 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3580 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3583 // allocate textures as needed
3584 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3586 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3587 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3589 if (p->texture_refraction)
3590 R_FreeTexture(p->texture_refraction);
3591 p->texture_refraction = NULL;
3592 if (p->texture_reflection)
3593 R_FreeTexture(p->texture_reflection);
3594 p->texture_reflection = NULL;
3596 memset(&r_waterstate, 0, sizeof(r_waterstate));
3597 r_waterstate.waterwidth = waterwidth;
3598 r_waterstate.waterheight = waterheight;
3599 r_waterstate.texturewidth = texturewidth;
3600 r_waterstate.textureheight = textureheight;
3603 if (r_waterstate.waterwidth)
3605 r_waterstate.enabled = true;
3607 // set up variables that will be used in shader setup
3608 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3609 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3610 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3611 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3614 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3615 r_waterstate.numwaterplanes = 0;
3618 void R_Water_AddWaterPlane(msurface_t *surface)
3620 int triangleindex, planeindex;
3626 r_waterstate_waterplane_t *p;
3627 texture_t *t = R_GetCurrentTexture(surface->texture);
3628 // just use the first triangle with a valid normal for any decisions
3629 VectorClear(normal);
3630 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3632 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3634 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3635 TriangleNormal(vert[0], vert[1], vert[2], normal);
3636 if (VectorLength2(normal) >= 0.001)
3640 VectorCopy(normal, plane.normal);
3641 VectorNormalize(plane.normal);
3642 plane.dist = DotProduct(vert[0], plane.normal);
3643 PlaneClassify(&plane);
3644 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3646 // skip backfaces (except if nocullface is set)
3647 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3649 VectorNegate(plane.normal, plane.normal);
3651 PlaneClassify(&plane);
3655 // find a matching plane if there is one
3656 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3657 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3659 if (planeindex >= r_waterstate.maxwaterplanes)
3660 return; // nothing we can do, out of planes
3662 // if this triangle does not fit any known plane rendered this frame, add one
3663 if (planeindex >= r_waterstate.numwaterplanes)
3665 // store the new plane
3666 r_waterstate.numwaterplanes++;
3668 // clear materialflags and pvs
3669 p->materialflags = 0;
3670 p->pvsvalid = false;
3672 // merge this surface's materialflags into the waterplane
3673 p->materialflags |= t->currentmaterialflags;
3674 // merge this surface's PVS into the waterplane
3675 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3676 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3677 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3679 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3684 static void R_Water_ProcessPlanes(void)
3686 r_refdef_view_t originalview;
3687 r_refdef_view_t myview;
3689 r_waterstate_waterplane_t *p;
3691 originalview = r_refdef.view;
3693 // make sure enough textures are allocated
3694 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3696 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3698 if (!p->texture_refraction)
3699 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);
3700 if (!p->texture_refraction)
3704 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3706 if (!p->texture_reflection)
3707 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);
3708 if (!p->texture_reflection)
3714 r_refdef.view = originalview;
3715 r_refdef.view.showdebug = false;
3716 r_refdef.view.width = r_waterstate.waterwidth;
3717 r_refdef.view.height = r_waterstate.waterheight;
3718 r_refdef.view.useclipplane = true;
3719 myview = r_refdef.view;
3720 r_waterstate.renderingscene = true;
3721 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3723 // render the normal view scene and copy into texture
3724 // (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)
3725 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3727 r_refdef.view = myview;
3728 r_refdef.view.clipplane = p->plane;
3729 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3730 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3731 PlaneClassify(&r_refdef.view.clipplane);
3733 R_ResetViewRendering3D();
3734 R_ClearScreen(r_refdef.fogenabled);
3738 // copy view into the screen texture
3739 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3740 GL_ActiveTexture(0);
3742 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
3745 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3747 r_refdef.view = myview;
3748 // render reflected scene and copy into texture
3749 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3750 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3751 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3752 r_refdef.view.clipplane = p->plane;
3753 // reverse the cullface settings for this render
3754 r_refdef.view.cullface_front = GL_FRONT;
3755 r_refdef.view.cullface_back = GL_BACK;
3756 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3758 r_refdef.view.usecustompvs = true;
3760 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3762 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3765 R_ResetViewRendering3D();
3766 R_ClearScreen(r_refdef.fogenabled);
3770 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3771 GL_ActiveTexture(0);
3773 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
3776 r_waterstate.renderingscene = false;
3777 r_refdef.view = originalview;
3778 R_ResetViewRendering3D();
3779 R_ClearScreen(r_refdef.fogenabled);
3783 r_refdef.view = originalview;
3784 r_waterstate.renderingscene = false;
3785 Cvar_SetValueQuick(&r_water, 0);
3786 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3790 void R_Bloom_StartFrame(void)
3792 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3794 // set bloomwidth and bloomheight to the bloom resolution that will be
3795 // used (often less than the screen resolution for faster rendering)
3796 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3797 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3798 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3799 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3800 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3802 // calculate desired texture sizes
3803 if (gl_support_arb_texture_non_power_of_two)
3805 screentexturewidth = r_refdef.view.width;
3806 screentextureheight = r_refdef.view.height;
3807 bloomtexturewidth = r_bloomstate.bloomwidth;
3808 bloomtextureheight = r_bloomstate.bloomheight;
3812 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3813 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3814 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3815 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3818 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3820 Cvar_SetValueQuick(&r_hdr, 0);
3821 Cvar_SetValueQuick(&r_bloom, 0);
3822 Cvar_SetValueQuick(&r_motionblur, 0);
3823 Cvar_SetValueQuick(&r_damageblur, 0);
3826 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3827 screentexturewidth = screentextureheight = 0;
3828 if (!r_hdr.integer && !r_bloom.integer)
3829 bloomtexturewidth = bloomtextureheight = 0;
3831 // allocate textures as needed
3832 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3834 if (r_bloomstate.texture_screen)
3835 R_FreeTexture(r_bloomstate.texture_screen);
3836 r_bloomstate.texture_screen = NULL;
3837 r_bloomstate.screentexturewidth = screentexturewidth;
3838 r_bloomstate.screentextureheight = screentextureheight;
3839 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3840 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);
3842 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3844 if (r_bloomstate.texture_bloom)
3845 R_FreeTexture(r_bloomstate.texture_bloom);
3846 r_bloomstate.texture_bloom = NULL;
3847 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3848 r_bloomstate.bloomtextureheight = bloomtextureheight;
3849 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3850 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);
3853 // set up a texcoord array for the full resolution screen image
3854 // (we have to keep this around to copy back during final render)
3855 r_bloomstate.screentexcoord2f[0] = 0;
3856 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3857 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3858 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3859 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3860 r_bloomstate.screentexcoord2f[5] = 0;
3861 r_bloomstate.screentexcoord2f[6] = 0;
3862 r_bloomstate.screentexcoord2f[7] = 0;
3864 // set up a texcoord array for the reduced resolution bloom image
3865 // (which will be additive blended over the screen image)
3866 r_bloomstate.bloomtexcoord2f[0] = 0;
3867 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3868 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3869 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3870 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3871 r_bloomstate.bloomtexcoord2f[5] = 0;
3872 r_bloomstate.bloomtexcoord2f[6] = 0;
3873 r_bloomstate.bloomtexcoord2f[7] = 0;
3875 if (r_hdr.integer || r_bloom.integer)
3877 r_bloomstate.enabled = true;
3878 r_bloomstate.hdr = r_hdr.integer != 0;
3882 void R_Bloom_CopyBloomTexture(float colorscale)
3884 r_refdef.stats.bloom++;
3886 // scale down screen texture to the bloom texture size
3888 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3889 GL_BlendFunc(GL_ONE, GL_ZERO);
3890 GL_Color(colorscale, colorscale, colorscale, 1);
3891 // TODO: optimize with multitexture or GLSL
3892 R_SetupGenericShader(true);
3893 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3894 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3895 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3896 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3898 // we now have a bloom image in the framebuffer
3899 // copy it into the bloom image texture for later processing
3900 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3901 GL_ActiveTexture(0);
3903 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
3904 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3907 void R_Bloom_CopyHDRTexture(void)
3909 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3910 GL_ActiveTexture(0);
3912 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
3913 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3916 void R_Bloom_MakeTexture(void)
3919 float xoffset, yoffset, r, brighten;
3921 r_refdef.stats.bloom++;
3923 R_ResetViewRendering2D();
3924 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3925 R_Mesh_ColorPointer(NULL, 0, 0);
3926 R_SetupGenericShader(true);
3928 // we have a bloom image in the framebuffer
3930 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3932 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3935 r = bound(0, r_bloom_colorexponent.value / x, 1);
3936 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3937 GL_Color(r, r, r, 1);
3938 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3939 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3940 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3941 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3943 // copy the vertically blurred bloom view to a texture
3944 GL_ActiveTexture(0);
3946 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
3947 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3950 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3951 brighten = r_bloom_brighten.value;
3953 brighten *= r_hdr_range.value;
3954 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3955 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3957 for (dir = 0;dir < 2;dir++)
3959 // blend on at multiple vertical offsets to achieve a vertical blur
3960 // TODO: do offset blends using GLSL
3961 GL_BlendFunc(GL_ONE, GL_ZERO);
3962 for (x = -range;x <= range;x++)
3964 if (!dir){xoffset = 0;yoffset = x;}
3965 else {xoffset = x;yoffset = 0;}
3966 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3967 yoffset /= (float)r_bloomstate.bloomtextureheight;
3968 // compute a texcoord array with the specified x and y offset
3969 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3970 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3971 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3972 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3973 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3974 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3975 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3976 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3977 // this r value looks like a 'dot' particle, fading sharply to
3978 // black at the edges
3979 // (probably not realistic but looks good enough)
3980 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3981 //r = (dir ? 1.0f : brighten)/(range*2+1);
3982 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3983 GL_Color(r, r, r, 1);
3984 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3985 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3986 GL_BlendFunc(GL_ONE, GL_ONE);
3989 // copy the vertically blurred bloom view to a texture
3990 GL_ActiveTexture(0);
3992 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
3993 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3996 // apply subtract last
3997 // (just like it would be in a GLSL shader)
3998 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4000 GL_BlendFunc(GL_ONE, GL_ZERO);
4001 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4002 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4003 GL_Color(1, 1, 1, 1);
4004 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4005 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4007 GL_BlendFunc(GL_ONE, GL_ONE);
4008 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4009 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4010 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4011 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4012 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4013 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4014 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4016 // copy the darkened bloom view to a texture
4017 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4018 GL_ActiveTexture(0);
4020 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
4021 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4025 void R_HDR_RenderBloomTexture(void)
4027 int oldwidth, oldheight;
4028 float oldcolorscale;
4030 oldcolorscale = r_refdef.view.colorscale;
4031 oldwidth = r_refdef.view.width;
4032 oldheight = r_refdef.view.height;
4033 r_refdef.view.width = r_bloomstate.bloomwidth;
4034 r_refdef.view.height = r_bloomstate.bloomheight;
4036 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4037 // TODO: add exposure compensation features
4038 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4040 r_refdef.view.showdebug = false;
4041 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4043 R_ResetViewRendering3D();
4045 R_ClearScreen(r_refdef.fogenabled);
4046 if (r_timereport_active)
4047 R_TimeReport("HDRclear");
4050 if (r_timereport_active)
4051 R_TimeReport("visibility");
4053 r_waterstate.numwaterplanes = 0;
4054 if (r_waterstate.enabled)
4055 R_RenderWaterPlanes();
4057 r_refdef.view.showdebug = true;
4059 r_waterstate.numwaterplanes = 0;
4061 R_ResetViewRendering2D();
4063 R_Bloom_CopyHDRTexture();
4064 R_Bloom_MakeTexture();
4066 // restore the view settings
4067 r_refdef.view.width = oldwidth;
4068 r_refdef.view.height = oldheight;
4069 r_refdef.view.colorscale = oldcolorscale;
4071 R_ResetViewRendering3D();
4073 R_ClearScreen(r_refdef.fogenabled);
4074 if (r_timereport_active)
4075 R_TimeReport("viewclear");
4078 static void R_BlendView(void)
4080 if (r_bloomstate.texture_screen)
4082 // make sure the buffer is available
4083 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4085 R_ResetViewRendering2D();
4086 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4087 R_Mesh_ColorPointer(NULL, 0, 0);
4088 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4089 GL_ActiveTexture(0);CHECKGLERROR
4091 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4093 // declare variables
4095 static float avgspeed;
4097 speed = VectorLength(cl.movement_velocity);
4099 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4100 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4102 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4103 speed = bound(0, speed, 1);
4104 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4106 // calculate values into a standard alpha
4107 cl.motionbluralpha = 1 - exp(-
4109 (r_motionblur.value * speed / 80)
4111 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4114 max(0.0001, cl.time - cl.oldtime) // fps independent
4117 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4118 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4120 if (cl.motionbluralpha > 0)
4122 R_SetupGenericShader(true);
4123 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4124 GL_Color(1, 1, 1, cl.motionbluralpha);
4125 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4126 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4127 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4128 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4132 // copy view into the screen texture
4133 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
4134 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
4137 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4139 unsigned int permutation =
4140 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
4141 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
4142 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4143 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4144 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4146 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4148 // render simple bloom effect
4149 // copy the screen and shrink it and darken it for the bloom process
4150 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4151 // make the bloom texture
4152 R_Bloom_MakeTexture();
4155 R_ResetViewRendering2D();
4156 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4157 R_Mesh_ColorPointer(NULL, 0, 0);
4158 GL_Color(1, 1, 1, 1);
4159 GL_BlendFunc(GL_ONE, GL_ZERO);
4160 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4161 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4162 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4163 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4164 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4165 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4166 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4167 if (r_glsl_permutation->loc_TintColor >= 0)
4168 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4169 if (r_glsl_permutation->loc_ClientTime >= 0)
4170 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4171 if (r_glsl_permutation->loc_PixelSize >= 0)
4172 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4173 if (r_glsl_permutation->loc_UserVec1 >= 0)
4175 float a=0, b=0, c=0, d=0;
4176 #if _MSC_VER >= 1400
4177 #define sscanf sscanf_s
4179 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4180 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4182 if (r_glsl_permutation->loc_UserVec2 >= 0)
4184 float a=0, b=0, c=0, d=0;
4185 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4186 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4188 if (r_glsl_permutation->loc_UserVec3 >= 0)
4190 float a=0, b=0, c=0, d=0;
4191 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4192 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4194 if (r_glsl_permutation->loc_UserVec4 >= 0)
4196 float a=0, b=0, c=0, d=0;
4197 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4198 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4200 if (r_glsl_permutation->loc_Saturation >= 0)
4201 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4202 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4203 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4209 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4211 // render high dynamic range bloom effect
4212 // the bloom texture was made earlier this render, so we just need to
4213 // blend it onto the screen...
4214 R_ResetViewRendering2D();
4215 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4216 R_Mesh_ColorPointer(NULL, 0, 0);
4217 R_SetupGenericShader(true);
4218 GL_Color(1, 1, 1, 1);
4219 GL_BlendFunc(GL_ONE, GL_ONE);
4220 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4221 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4222 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4223 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4225 else if (r_bloomstate.texture_bloom)
4227 // render simple bloom effect
4228 // copy the screen and shrink it and darken it for the bloom process
4229 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4230 // make the bloom texture
4231 R_Bloom_MakeTexture();
4232 // put the original screen image back in place and blend the bloom
4234 R_ResetViewRendering2D();
4235 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4236 R_Mesh_ColorPointer(NULL, 0, 0);
4237 GL_Color(1, 1, 1, 1);
4238 GL_BlendFunc(GL_ONE, GL_ZERO);
4239 // do both in one pass if possible
4240 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4241 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4242 if (r_textureunits.integer >= 2 && gl_combine.integer)
4244 R_SetupGenericTwoTextureShader(GL_ADD);
4245 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4246 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4250 R_SetupGenericShader(true);
4251 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4252 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4253 // now blend on the bloom texture
4254 GL_BlendFunc(GL_ONE, GL_ONE);
4255 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4256 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4258 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4259 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4261 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4263 // apply a color tint to the whole view
4264 R_ResetViewRendering2D();
4265 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4266 R_Mesh_ColorPointer(NULL, 0, 0);
4267 R_SetupGenericShader(false);
4268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4269 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4270 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4274 matrix4x4_t r_waterscrollmatrix;
4276 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4278 if (r_refdef.fog_density)
4280 r_refdef.fogcolor[0] = r_refdef.fog_red;
4281 r_refdef.fogcolor[1] = r_refdef.fog_green;
4282 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4286 VectorCopy(r_refdef.fogcolor, fogvec);
4287 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
4289 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
4290 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
4291 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
4292 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
4294 // color.rgb *= ContrastBoost * SceneBrightness;
4295 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4296 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4297 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4298 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4303 void R_UpdateVariables(void)
4307 r_refdef.scene.ambient = r_ambient.value;
4309 r_refdef.farclip = 4096;
4310 if (r_refdef.scene.worldmodel)
4311 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4312 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4314 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4315 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4316 r_refdef.polygonfactor = 0;
4317 r_refdef.polygonoffset = 0;
4318 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4319 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4321 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4322 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4323 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4324 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4325 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4326 if (r_showsurfaces.integer)
4328 r_refdef.scene.rtworld = false;
4329 r_refdef.scene.rtworldshadows = false;
4330 r_refdef.scene.rtdlight = false;
4331 r_refdef.scene.rtdlightshadows = false;
4332 r_refdef.lightmapintensity = 0;
4335 if (gamemode == GAME_NEHAHRA)
4337 if (gl_fogenable.integer)
4339 r_refdef.oldgl_fogenable = true;
4340 r_refdef.fog_density = gl_fogdensity.value;
4341 r_refdef.fog_red = gl_fogred.value;
4342 r_refdef.fog_green = gl_foggreen.value;
4343 r_refdef.fog_blue = gl_fogblue.value;
4344 r_refdef.fog_alpha = 1;
4345 r_refdef.fog_start = 0;
4346 r_refdef.fog_end = gl_skyclip.value;
4348 else if (r_refdef.oldgl_fogenable)
4350 r_refdef.oldgl_fogenable = false;
4351 r_refdef.fog_density = 0;
4352 r_refdef.fog_red = 0;
4353 r_refdef.fog_green = 0;
4354 r_refdef.fog_blue = 0;
4355 r_refdef.fog_alpha = 0;
4356 r_refdef.fog_start = 0;
4357 r_refdef.fog_end = 0;
4361 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4362 r_refdef.fog_start = max(0, r_refdef.fog_start);
4363 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4365 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4367 if (r_refdef.fog_density && r_drawfog.integer)
4369 r_refdef.fogenabled = true;
4370 // this is the point where the fog reaches 0.9986 alpha, which we
4371 // consider a good enough cutoff point for the texture
4372 // (0.9986 * 256 == 255.6)
4373 if (r_fog_exp2.integer)
4374 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4376 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4377 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4378 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4379 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4380 // fog color was already set
4381 // update the fog texture
4382 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)
4383 R_BuildFogTexture();
4386 r_refdef.fogenabled = false;
4388 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4390 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4392 // build GLSL gamma texture
4393 #define RAMPWIDTH 256
4394 unsigned short ramp[RAMPWIDTH * 3];
4395 unsigned char rampbgr[RAMPWIDTH][4];
4398 r_texture_gammaramps_serial = vid_gammatables_serial;
4400 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4401 for(i = 0; i < RAMPWIDTH; ++i)
4403 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4404 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4405 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4408 if (r_texture_gammaramps)
4410 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4414 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);
4420 // remove GLSL gamma texture
4424 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4425 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4431 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4432 if( scenetype != r_currentscenetype ) {
4433 // store the old scenetype
4434 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4435 r_currentscenetype = scenetype;
4436 // move in the new scene
4437 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4446 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4448 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4449 if( scenetype == r_currentscenetype ) {
4450 return &r_refdef.scene;
4452 return &r_scenes_store[ scenetype ];
4461 void R_RenderView(void)
4463 if (r_timereport_active)
4464 R_TimeReport("start");
4465 r_frame++; // used only by R_GetCurrentTexture
4466 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4468 R_AnimCache_NewFrame();
4470 if (r_refdef.view.isoverlay)
4472 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4473 GL_Clear( GL_DEPTH_BUFFER_BIT );
4474 R_TimeReport("depthclear");
4476 r_refdef.view.showdebug = false;
4478 r_waterstate.enabled = false;
4479 r_waterstate.numwaterplanes = 0;
4487 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4488 return; //Host_Error ("R_RenderView: NULL worldmodel");
4490 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4492 // break apart the view matrix into vectors for various purposes
4493 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4494 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4495 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4496 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4497 // make an inverted copy of the view matrix for tracking sprites
4498 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4500 R_Shadow_UpdateWorldLightSelection();
4502 R_Bloom_StartFrame();
4503 R_Water_StartFrame();
4506 if (r_timereport_active)
4507 R_TimeReport("viewsetup");
4509 R_ResetViewRendering3D();
4511 if (r_refdef.view.clear || r_refdef.fogenabled)
4513 R_ClearScreen(r_refdef.fogenabled);
4514 if (r_timereport_active)
4515 R_TimeReport("viewclear");
4517 r_refdef.view.clear = true;
4519 // this produces a bloom texture to be used in R_BlendView() later
4521 R_HDR_RenderBloomTexture();
4523 r_refdef.view.showdebug = true;
4526 if (r_timereport_active)
4527 R_TimeReport("visibility");
4529 r_waterstate.numwaterplanes = 0;
4530 if (r_waterstate.enabled)
4531 R_RenderWaterPlanes();
4534 r_waterstate.numwaterplanes = 0;
4537 if (r_timereport_active)
4538 R_TimeReport("blendview");
4540 GL_Scissor(0, 0, vid.width, vid.height);
4541 GL_ScissorTest(false);
4545 void R_RenderWaterPlanes(void)
4547 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4549 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4550 if (r_timereport_active)
4551 R_TimeReport("waterworld");
4554 // don't let sound skip if going slow
4555 if (r_refdef.scene.extraupdate)
4558 R_DrawModelsAddWaterPlanes();
4559 if (r_timereport_active)
4560 R_TimeReport("watermodels");
4562 if (r_waterstate.numwaterplanes)
4564 R_Water_ProcessPlanes();
4565 if (r_timereport_active)
4566 R_TimeReport("waterscenes");
4570 extern void R_DrawLightningBeams (void);
4571 extern void VM_CL_AddPolygonsToMeshQueue (void);
4572 extern void R_DrawPortals (void);
4573 extern cvar_t cl_locs_show;
4574 static void R_DrawLocs(void);
4575 static void R_DrawEntityBBoxes(void);
4576 void R_RenderScene(void)
4578 r_refdef.stats.renders++;
4582 // don't let sound skip if going slow
4583 if (r_refdef.scene.extraupdate)
4586 R_MeshQueue_BeginScene();
4590 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);
4592 if (cl.csqc_vidvars.drawworld)
4594 // don't let sound skip if going slow
4595 if (r_refdef.scene.extraupdate)
4598 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4600 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4601 if (r_timereport_active)
4602 R_TimeReport("worldsky");
4605 if (R_DrawBrushModelsSky() && r_timereport_active)
4606 R_TimeReport("bmodelsky");
4609 R_AnimCache_CacheVisibleEntities();
4611 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4613 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4614 if (r_timereport_active)
4615 R_TimeReport("worlddepth");
4617 if (r_depthfirst.integer >= 2)
4619 R_DrawModelsDepth();
4620 if (r_timereport_active)
4621 R_TimeReport("modeldepth");
4624 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4626 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4627 if (r_timereport_active)
4628 R_TimeReport("world");
4631 // don't let sound skip if going slow
4632 if (r_refdef.scene.extraupdate)
4636 if (r_timereport_active)
4637 R_TimeReport("models");
4639 // don't let sound skip if going slow
4640 if (r_refdef.scene.extraupdate)
4643 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4645 R_DrawModelShadows();
4646 R_ResetViewRendering3D();
4647 // don't let sound skip if going slow
4648 if (r_refdef.scene.extraupdate)
4652 R_ShadowVolumeLighting(false);
4653 if (r_timereport_active)
4654 R_TimeReport("rtlights");
4656 // don't let sound skip if going slow
4657 if (r_refdef.scene.extraupdate)
4660 if (r_shadows.integer > 0 && r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4662 R_DrawModelShadows();
4663 R_ResetViewRendering3D();
4664 // don't let sound skip if going slow
4665 if (r_refdef.scene.extraupdate)
4669 if (cl.csqc_vidvars.drawworld)
4671 R_DrawLightningBeams();
4672 if (r_timereport_active)
4673 R_TimeReport("lightning");
4676 if (r_timereport_active)
4677 R_TimeReport("decals");
4680 if (r_timereport_active)
4681 R_TimeReport("particles");
4684 if (r_timereport_active)
4685 R_TimeReport("explosions");
4688 R_SetupGenericShader(true);
4689 VM_CL_AddPolygonsToMeshQueue();
4691 if (r_refdef.view.showdebug)
4693 if (cl_locs_show.integer)
4696 if (r_timereport_active)
4697 R_TimeReport("showlocs");
4700 if (r_drawportals.integer)
4703 if (r_timereport_active)
4704 R_TimeReport("portals");
4707 if (r_showbboxes.value > 0)
4709 R_DrawEntityBBoxes();
4710 if (r_timereport_active)
4711 R_TimeReport("bboxes");
4715 R_SetupGenericShader(true);
4716 R_MeshQueue_RenderTransparent();
4717 if (r_timereport_active)
4718 R_TimeReport("drawtrans");
4720 R_SetupGenericShader(true);
4722 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))
4724 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4725 if (r_timereport_active)
4726 R_TimeReport("worlddebug");
4727 R_DrawModelsDebug();
4728 if (r_timereport_active)
4729 R_TimeReport("modeldebug");
4732 R_SetupGenericShader(true);
4734 if (cl.csqc_vidvars.drawworld)
4737 if (r_timereport_active)
4738 R_TimeReport("coronas");
4741 // don't let sound skip if going slow
4742 if (r_refdef.scene.extraupdate)
4745 R_ResetViewRendering2D();
4748 static const unsigned short bboxelements[36] =
4758 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4761 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4762 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4763 GL_DepthMask(false);
4764 GL_DepthRange(0, 1);
4765 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4766 R_Mesh_Matrix(&identitymatrix);
4767 R_Mesh_ResetTextureState();
4769 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4770 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4771 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4772 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4773 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4774 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4775 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4776 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4777 R_FillColors(color4f, 8, cr, cg, cb, ca);
4778 if (r_refdef.fogenabled)
4780 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4782 f1 = FogPoint_World(v);
4784 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4785 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4786 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4789 R_Mesh_VertexPointer(vertex3f, 0, 0);
4790 R_Mesh_ColorPointer(color4f, 0, 0);
4791 R_Mesh_ResetTextureState();
4792 R_SetupGenericShader(false);
4793 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4796 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4800 prvm_edict_t *edict;
4801 prvm_prog_t *prog_save = prog;
4803 // this function draws bounding boxes of server entities
4807 GL_CullFace(GL_NONE);
4808 R_SetupGenericShader(false);
4812 for (i = 0;i < numsurfaces;i++)
4814 edict = PRVM_EDICT_NUM(surfacelist[i]);
4815 switch ((int)edict->fields.server->solid)
4817 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4818 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4819 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4820 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4821 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4822 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4824 color[3] *= r_showbboxes.value;
4825 color[3] = bound(0, color[3], 1);
4826 GL_DepthTest(!r_showdisabledepthtest.integer);
4827 GL_CullFace(r_refdef.view.cullface_front);
4828 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4834 static void R_DrawEntityBBoxes(void)
4837 prvm_edict_t *edict;
4839 prvm_prog_t *prog_save = prog;
4841 // this function draws bounding boxes of server entities
4847 for (i = 0;i < prog->num_edicts;i++)
4849 edict = PRVM_EDICT_NUM(i);
4850 if (edict->priv.server->free)
4852 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4853 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4855 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4857 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4858 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4864 unsigned short nomodelelements[24] =
4876 float nomodelvertex3f[6*3] =
4886 float nomodelcolor4f[6*4] =
4888 0.0f, 0.0f, 0.5f, 1.0f,
4889 0.0f, 0.0f, 0.5f, 1.0f,
4890 0.0f, 0.5f, 0.0f, 1.0f,
4891 0.0f, 0.5f, 0.0f, 1.0f,
4892 0.5f, 0.0f, 0.0f, 1.0f,
4893 0.5f, 0.0f, 0.0f, 1.0f
4896 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4901 // this is only called once per entity so numsurfaces is always 1, and
4902 // surfacelist is always {0}, so this code does not handle batches
4903 R_Mesh_Matrix(&ent->matrix);
4905 if (ent->flags & EF_ADDITIVE)
4907 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4908 GL_DepthMask(false);
4910 else if (ent->alpha < 1)
4912 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4913 GL_DepthMask(false);
4917 GL_BlendFunc(GL_ONE, GL_ZERO);
4920 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4921 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4922 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4923 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4924 R_SetupGenericShader(false);
4925 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4926 if (r_refdef.fogenabled)
4929 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4930 R_Mesh_ColorPointer(color4f, 0, 0);
4931 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4932 f1 = FogPoint_World(org);
4934 for (i = 0, c = color4f;i < 6;i++, c += 4)
4936 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4937 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4938 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4942 else if (ent->alpha != 1)
4944 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4945 R_Mesh_ColorPointer(color4f, 0, 0);
4946 for (i = 0, c = color4f;i < 6;i++, c += 4)
4950 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4951 R_Mesh_ResetTextureState();
4952 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4955 void R_DrawNoModel(entity_render_t *ent)
4958 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4959 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4960 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4962 // R_DrawNoModelCallback(ent, 0);
4965 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4967 vec3_t right1, right2, diff, normal;
4969 VectorSubtract (org2, org1, normal);
4971 // calculate 'right' vector for start
4972 VectorSubtract (r_refdef.view.origin, org1, diff);
4973 CrossProduct (normal, diff, right1);
4974 VectorNormalize (right1);
4976 // calculate 'right' vector for end
4977 VectorSubtract (r_refdef.view.origin, org2, diff);
4978 CrossProduct (normal, diff, right2);
4979 VectorNormalize (right2);
4981 vert[ 0] = org1[0] + width * right1[0];
4982 vert[ 1] = org1[1] + width * right1[1];
4983 vert[ 2] = org1[2] + width * right1[2];
4984 vert[ 3] = org1[0] - width * right1[0];
4985 vert[ 4] = org1[1] - width * right1[1];
4986 vert[ 5] = org1[2] - width * right1[2];
4987 vert[ 6] = org2[0] - width * right2[0];
4988 vert[ 7] = org2[1] - width * right2[1];
4989 vert[ 8] = org2[2] - width * right2[2];
4990 vert[ 9] = org2[0] + width * right2[0];
4991 vert[10] = org2[1] + width * right2[1];
4992 vert[11] = org2[2] + width * right2[2];
4995 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4997 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)
4999 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5003 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5004 fog = FogPoint_World(origin);
5006 R_Mesh_Matrix(&identitymatrix);
5007 GL_BlendFunc(blendfunc1, blendfunc2);
5009 GL_CullFace(GL_NONE);
5011 GL_DepthMask(false);
5012 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5013 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5014 GL_DepthTest(!depthdisable);
5016 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5017 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5018 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5019 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5020 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5021 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5022 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5023 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5024 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5025 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5026 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5027 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5029 R_Mesh_VertexPointer(vertex3f, 0, 0);
5030 R_Mesh_ColorPointer(NULL, 0, 0);
5031 R_Mesh_ResetTextureState();
5032 R_SetupGenericShader(true);
5033 R_Mesh_TexBind(0, R_GetTexture(texture));
5034 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5035 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5036 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5037 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5039 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5041 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5042 GL_BlendFunc(blendfunc1, GL_ONE);
5044 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5045 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5049 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5054 VectorSet(v, x, y, z);
5055 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5056 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5058 if (i == mesh->numvertices)
5060 if (mesh->numvertices < mesh->maxvertices)
5062 VectorCopy(v, vertex3f);
5063 mesh->numvertices++;
5065 return mesh->numvertices;
5071 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5075 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5076 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5077 e = mesh->element3i + mesh->numtriangles * 3;
5078 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5080 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5081 if (mesh->numtriangles < mesh->maxtriangles)
5086 mesh->numtriangles++;
5088 element[1] = element[2];
5092 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5096 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5097 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5098 e = mesh->element3i + mesh->numtriangles * 3;
5099 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5101 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5102 if (mesh->numtriangles < mesh->maxtriangles)
5107 mesh->numtriangles++;
5109 element[1] = element[2];
5113 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5114 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5116 int planenum, planenum2;
5119 mplane_t *plane, *plane2;
5121 double temppoints[2][256*3];
5122 // figure out how large a bounding box we need to properly compute this brush
5124 for (w = 0;w < numplanes;w++)
5125 maxdist = max(maxdist, planes[w].dist);
5126 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5127 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5128 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5132 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5133 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5135 if (planenum2 == planenum)
5137 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);
5140 if (tempnumpoints < 3)
5142 // generate elements forming a triangle fan for this polygon
5143 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5147 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)
5149 texturelayer_t *layer;
5150 layer = t->currentlayers + t->currentnumlayers++;
5152 layer->depthmask = depthmask;
5153 layer->blendfunc1 = blendfunc1;
5154 layer->blendfunc2 = blendfunc2;
5155 layer->texture = texture;
5156 layer->texmatrix = *matrix;
5157 layer->color[0] = r * r_refdef.view.colorscale;
5158 layer->color[1] = g * r_refdef.view.colorscale;
5159 layer->color[2] = b * r_refdef.view.colorscale;
5160 layer->color[3] = a;
5163 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5166 index = parms[2] + r_refdef.scene.time * parms[3];
5167 index -= floor(index);
5171 case Q3WAVEFUNC_NONE:
5172 case Q3WAVEFUNC_NOISE:
5173 case Q3WAVEFUNC_COUNT:
5176 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5177 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5178 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5179 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5180 case Q3WAVEFUNC_TRIANGLE:
5182 f = index - floor(index);
5193 return (float)(parms[0] + parms[1] * f);
5196 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5201 matrix4x4_t matrix, temp;
5202 switch(tcmod->tcmod)
5206 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5207 matrix = r_waterscrollmatrix;
5209 matrix = identitymatrix;
5211 case Q3TCMOD_ENTITYTRANSLATE:
5212 // this is used in Q3 to allow the gamecode to control texcoord
5213 // scrolling on the entity, which is not supported in darkplaces yet.
5214 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5216 case Q3TCMOD_ROTATE:
5217 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5218 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5219 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5222 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5224 case Q3TCMOD_SCROLL:
5225 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5227 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5228 w = (int) tcmod->parms[0];
5229 h = (int) tcmod->parms[1];
5230 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5232 idx = (int) floor(f * w * h);
5233 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5235 case Q3TCMOD_STRETCH:
5236 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5237 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5239 case Q3TCMOD_TRANSFORM:
5240 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5241 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5242 VectorSet(tcmat + 6, 0 , 0 , 1);
5243 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5244 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5246 case Q3TCMOD_TURBULENT:
5247 // this is handled in the RSurf_PrepareVertices function
5248 matrix = identitymatrix;
5252 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5255 texture_t *R_GetCurrentTexture(texture_t *t)
5258 const entity_render_t *ent = rsurface.entity;
5259 dp_model_t *model = ent->model;
5260 q3shaderinfo_layer_tcmod_t *tcmod;
5262 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5263 return t->currentframe;
5264 t->update_lastrenderframe = r_frame;
5265 t->update_lastrenderentity = (void *)ent;
5267 // switch to an alternate material if this is a q1bsp animated material
5269 texture_t *texture = t;
5270 int s = ent->skinnum;
5271 if ((unsigned int)s >= (unsigned int)model->numskins)
5273 if (model->skinscenes)
5275 if (model->skinscenes[s].framecount > 1)
5276 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5278 s = model->skinscenes[s].firstframe;
5281 t = t + s * model->num_surfaces;
5284 // use an alternate animation if the entity's frame is not 0,
5285 // and only if the texture has an alternate animation
5286 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5287 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5289 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5291 texture->currentframe = t;
5294 // update currentskinframe to be a qw skin or animation frame
5295 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"))
5297 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5299 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5300 if (developer_loading.integer)
5301 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5302 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);
5304 t->currentskinframe = r_qwskincache_skinframe[i];
5305 if (t->currentskinframe == NULL)
5306 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5308 else if (t->numskinframes >= 2)
5309 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5310 if (t->backgroundnumskinframes >= 2)
5311 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5313 t->currentmaterialflags = t->basematerialflags;
5314 t->currentalpha = ent->alpha;
5315 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5316 t->currentalpha *= r_wateralpha.value;
5317 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5318 t->currentalpha *= t->r_water_wateralpha;
5319 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5320 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5321 if (!(ent->flags & RENDER_LIGHT))
5322 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5323 else if (rsurface.modeltexcoordlightmap2f == NULL)
5325 // pick a model lighting mode
5326 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5327 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5329 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5331 if (ent->effects & EF_ADDITIVE)
5332 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5333 else if (t->currentalpha < 1)
5334 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5335 if (ent->effects & EF_DOUBLESIDED)
5336 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5337 if (ent->effects & EF_NODEPTHTEST)
5338 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5339 if (ent->flags & RENDER_VIEWMODEL)
5340 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5341 if (t->backgroundnumskinframes)
5342 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5343 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5345 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5346 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5349 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5351 // there is no tcmod
5352 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5354 t->currenttexmatrix = r_waterscrollmatrix;
5355 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5359 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5360 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5363 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5364 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5365 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5366 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5368 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5369 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5370 t->glosstexture = r_texture_black;
5371 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5372 t->backgroundglosstexture = r_texture_black;
5373 t->specularpower = r_shadow_glossexponent.value;
5374 // TODO: store reference values for these in the texture?
5375 t->specularscale = 0;
5376 if (r_shadow_gloss.integer > 0)
5378 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5380 if (r_shadow_glossintensity.value > 0)
5382 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5383 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5384 t->specularscale = r_shadow_glossintensity.value;
5387 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5389 t->glosstexture = r_texture_white;
5390 t->backgroundglosstexture = r_texture_white;
5391 t->specularscale = r_shadow_gloss2intensity.value;
5395 // lightmaps mode looks bad with dlights using actual texturing, so turn
5396 // off the colormap and glossmap, but leave the normalmap on as it still
5397 // accurately represents the shading involved
5398 if (gl_lightmaps.integer)
5400 t->basetexture = r_texture_grey128;
5401 t->backgroundbasetexture = NULL;
5402 t->specularscale = 0;
5403 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5406 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5407 VectorClear(t->dlightcolor);
5408 t->currentnumlayers = 0;
5409 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5412 int blendfunc1, blendfunc2;
5414 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5416 blendfunc1 = GL_SRC_ALPHA;
5417 blendfunc2 = GL_ONE;
5419 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5421 blendfunc1 = GL_SRC_ALPHA;
5422 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5424 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5426 blendfunc1 = t->customblendfunc[0];
5427 blendfunc2 = t->customblendfunc[1];
5431 blendfunc1 = GL_ONE;
5432 blendfunc2 = GL_ZERO;
5434 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5435 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5436 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5437 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5439 // fullbright is not affected by r_refdef.lightmapintensity
5440 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]);
5441 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5442 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]);
5443 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5444 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]);
5448 vec3_t ambientcolor;
5450 // set the color tint used for lights affecting this surface
5451 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5453 // q3bsp has no lightmap updates, so the lightstylevalue that
5454 // would normally be baked into the lightmap must be
5455 // applied to the color
5456 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5457 if (ent->model->type == mod_brushq3)
5458 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5459 colorscale *= r_refdef.lightmapintensity;
5460 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5461 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5462 // basic lit geometry
5463 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]);
5464 // add pants/shirt if needed
5465 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5466 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]);
5467 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5468 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]);
5469 // now add ambient passes if needed
5470 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5472 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]);
5473 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5474 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]);
5475 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5476 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]);
5479 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5480 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]);
5481 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5483 // if this is opaque use alpha blend which will darken the earlier
5486 // if this is an alpha blended material, all the earlier passes
5487 // were darkened by fog already, so we only need to add the fog
5488 // color ontop through the fog mask texture
5490 // if this is an additive blended material, all the earlier passes
5491 // were darkened by fog already, and we should not add fog color
5492 // (because the background was not darkened, there is no fog color
5493 // that was lost behind it).
5494 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]);
5498 return t->currentframe;
5501 rsurfacestate_t rsurface;
5503 void R_Mesh_ResizeArrays(int newvertices)
5506 if (rsurface.array_size >= newvertices)
5508 if (rsurface.array_modelvertex3f)
5509 Mem_Free(rsurface.array_modelvertex3f);
5510 rsurface.array_size = (newvertices + 1023) & ~1023;
5511 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5512 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5513 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5514 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5515 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5516 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5517 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5518 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5519 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5520 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5521 rsurface.array_color4f = base + rsurface.array_size * 27;
5522 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5525 void RSurf_ActiveWorldEntity(void)
5527 dp_model_t *model = r_refdef.scene.worldmodel;
5528 //if (rsurface.entity == r_refdef.scene.worldentity)
5530 rsurface.entity = r_refdef.scene.worldentity;
5531 if (rsurface.array_size < model->surfmesh.num_vertices)
5532 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5533 rsurface.matrix = identitymatrix;
5534 rsurface.inversematrix = identitymatrix;
5535 R_Mesh_Matrix(&identitymatrix);
5536 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5537 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5538 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5539 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5540 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5541 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5542 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5543 rsurface.frameblend[0].lerp = 1;
5544 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5545 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5546 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5547 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5548 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5549 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5550 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5551 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5552 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5553 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5554 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5555 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5556 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5557 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5558 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5559 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5560 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5561 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5562 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5563 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5564 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5565 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5566 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5567 rsurface.modelelement3i = model->surfmesh.data_element3i;
5568 rsurface.modelelement3s = model->surfmesh.data_element3s;
5569 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5570 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5571 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5572 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5573 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5574 rsurface.modelsurfaces = model->data_surfaces;
5575 rsurface.generatedvertex = false;
5576 rsurface.vertex3f = rsurface.modelvertex3f;
5577 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5578 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5579 rsurface.svector3f = rsurface.modelsvector3f;
5580 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5581 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5582 rsurface.tvector3f = rsurface.modeltvector3f;
5583 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5584 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5585 rsurface.normal3f = rsurface.modelnormal3f;
5586 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5587 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5588 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5591 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5593 dp_model_t *model = ent->model;
5594 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5596 rsurface.entity = (entity_render_t *)ent;
5597 if (rsurface.array_size < model->surfmesh.num_vertices)
5598 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5599 rsurface.matrix = ent->matrix;
5600 rsurface.inversematrix = ent->inversematrix;
5601 R_Mesh_Matrix(&rsurface.matrix);
5602 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5603 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5604 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5605 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5606 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5607 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5608 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5609 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5610 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5611 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5612 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5613 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5614 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5615 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5616 if (ent->model->brush.submodel)
5618 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5619 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5621 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5623 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5625 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5626 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5627 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5628 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5630 else if (wanttangents)
5632 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5633 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5634 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5635 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5636 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5638 else if (wantnormals)
5640 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5641 rsurface.modelsvector3f = NULL;
5642 rsurface.modeltvector3f = NULL;
5643 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5644 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5648 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5649 rsurface.modelsvector3f = NULL;
5650 rsurface.modeltvector3f = NULL;
5651 rsurface.modelnormal3f = NULL;
5652 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5654 rsurface.modelvertex3f_bufferobject = 0;
5655 rsurface.modelvertex3f_bufferoffset = 0;
5656 rsurface.modelsvector3f_bufferobject = 0;
5657 rsurface.modelsvector3f_bufferoffset = 0;
5658 rsurface.modeltvector3f_bufferobject = 0;
5659 rsurface.modeltvector3f_bufferoffset = 0;
5660 rsurface.modelnormal3f_bufferobject = 0;
5661 rsurface.modelnormal3f_bufferoffset = 0;
5662 rsurface.generatedvertex = true;
5666 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5667 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5668 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5669 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5670 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5671 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5672 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5673 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5674 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5675 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5676 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5677 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5678 rsurface.generatedvertex = false;
5680 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5681 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5682 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5683 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5684 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5685 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5686 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5687 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5688 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5689 rsurface.modelelement3i = model->surfmesh.data_element3i;
5690 rsurface.modelelement3s = model->surfmesh.data_element3s;
5691 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5692 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5693 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5694 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5695 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5696 rsurface.modelsurfaces = model->data_surfaces;
5697 rsurface.vertex3f = rsurface.modelvertex3f;
5698 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5699 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5700 rsurface.svector3f = rsurface.modelsvector3f;
5701 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5702 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5703 rsurface.tvector3f = rsurface.modeltvector3f;
5704 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5705 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5706 rsurface.normal3f = rsurface.modelnormal3f;
5707 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5708 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5709 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5712 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5713 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5716 int texturesurfaceindex;
5721 const float *v1, *in_tc;
5723 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5725 q3shaderinfo_deform_t *deform;
5726 // 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
5727 if (rsurface.generatedvertex)
5729 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5730 generatenormals = true;
5731 for (i = 0;i < Q3MAXDEFORMS;i++)
5733 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5735 generatetangents = true;
5736 generatenormals = true;
5738 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5739 generatenormals = true;
5741 if (generatenormals && !rsurface.modelnormal3f)
5743 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5744 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5745 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5746 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5748 if (generatetangents && !rsurface.modelsvector3f)
5750 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5751 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5752 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5753 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5754 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5755 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5756 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 != 0);
5759 rsurface.vertex3f = rsurface.modelvertex3f;
5760 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5761 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5762 rsurface.svector3f = rsurface.modelsvector3f;
5763 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5764 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5765 rsurface.tvector3f = rsurface.modeltvector3f;
5766 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5767 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5768 rsurface.normal3f = rsurface.modelnormal3f;
5769 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5770 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5771 // if vertices are deformed (sprite flares and things in maps, possibly
5772 // water waves, bulges and other deformations), generate them into
5773 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5774 // (may be static model data or generated data for an animated model, or
5775 // the previous deform pass)
5776 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5778 switch (deform->deform)
5781 case Q3DEFORM_PROJECTIONSHADOW:
5782 case Q3DEFORM_TEXT0:
5783 case Q3DEFORM_TEXT1:
5784 case Q3DEFORM_TEXT2:
5785 case Q3DEFORM_TEXT3:
5786 case Q3DEFORM_TEXT4:
5787 case Q3DEFORM_TEXT5:
5788 case Q3DEFORM_TEXT6:
5789 case Q3DEFORM_TEXT7:
5792 case Q3DEFORM_AUTOSPRITE:
5793 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5794 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5795 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5796 VectorNormalize(newforward);
5797 VectorNormalize(newright);
5798 VectorNormalize(newup);
5799 // make deformed versions of only the model vertices used by the specified surfaces
5800 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5803 // a single autosprite surface can contain multiple sprites...
5804 for (j = 0;j < surface->num_vertices - 3;j += 4)
5806 VectorClear(center);
5807 for (i = 0;i < 4;i++)
5808 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5809 VectorScale(center, 0.25f, center);
5810 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5811 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5812 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5813 for (i = 0;i < 4;i++)
5815 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5816 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5819 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 != 0);
5820 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 != 0);
5822 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5823 rsurface.vertex3f_bufferobject = 0;
5824 rsurface.vertex3f_bufferoffset = 0;
5825 rsurface.svector3f = rsurface.array_deformedsvector3f;
5826 rsurface.svector3f_bufferobject = 0;
5827 rsurface.svector3f_bufferoffset = 0;
5828 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5829 rsurface.tvector3f_bufferobject = 0;
5830 rsurface.tvector3f_bufferoffset = 0;
5831 rsurface.normal3f = rsurface.array_deformednormal3f;
5832 rsurface.normal3f_bufferobject = 0;
5833 rsurface.normal3f_bufferoffset = 0;
5835 case Q3DEFORM_AUTOSPRITE2:
5836 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5837 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5838 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5839 VectorNormalize(newforward);
5840 VectorNormalize(newright);
5841 VectorNormalize(newup);
5842 // make deformed versions of only the model vertices used by the specified surfaces
5843 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5845 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5846 const float *v1, *v2;
5856 memset(shortest, 0, sizeof(shortest));
5857 // a single autosprite surface can contain multiple sprites...
5858 for (j = 0;j < surface->num_vertices - 3;j += 4)
5860 VectorClear(center);
5861 for (i = 0;i < 4;i++)
5862 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5863 VectorScale(center, 0.25f, center);
5864 // find the two shortest edges, then use them to define the
5865 // axis vectors for rotating around the central axis
5866 for (i = 0;i < 6;i++)
5868 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5869 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5871 Debug_PolygonBegin(NULL, 0);
5872 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5873 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);
5874 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5877 l = VectorDistance2(v1, v2);
5878 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5880 l += (1.0f / 1024.0f);
5881 if (shortest[0].length2 > l || i == 0)
5883 shortest[1] = shortest[0];
5884 shortest[0].length2 = l;
5885 shortest[0].v1 = v1;
5886 shortest[0].v2 = v2;
5888 else if (shortest[1].length2 > l || i == 1)
5890 shortest[1].length2 = l;
5891 shortest[1].v1 = v1;
5892 shortest[1].v2 = v2;
5895 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5896 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5898 Debug_PolygonBegin(NULL, 0);
5899 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5900 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);
5901 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5904 // this calculates the right vector from the shortest edge
5905 // and the up vector from the edge midpoints
5906 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5907 VectorNormalize(right);
5908 VectorSubtract(end, start, up);
5909 VectorNormalize(up);
5910 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5911 VectorSubtract(rsurface.modelorg, center, forward);
5912 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5913 VectorNegate(forward, forward);
5914 VectorReflect(forward, 0, up, forward);
5915 VectorNormalize(forward);
5916 CrossProduct(up, forward, newright);
5917 VectorNormalize(newright);
5919 Debug_PolygonBegin(NULL, 0);
5920 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);
5921 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5922 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5926 Debug_PolygonBegin(NULL, 0);
5927 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5928 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5929 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5932 // rotate the quad around the up axis vector, this is made
5933 // especially easy by the fact we know the quad is flat,
5934 // so we only have to subtract the center position and
5935 // measure distance along the right vector, and then
5936 // multiply that by the newright vector and add back the
5938 // we also need to subtract the old position to undo the
5939 // displacement from the center, which we do with a
5940 // DotProduct, the subtraction/addition of center is also
5941 // optimized into DotProducts here
5942 l = DotProduct(right, center);
5943 for (i = 0;i < 4;i++)
5945 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5946 f = DotProduct(right, v1) - l;
5947 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5950 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 != 0);
5951 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 != 0);
5953 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5954 rsurface.vertex3f_bufferobject = 0;
5955 rsurface.vertex3f_bufferoffset = 0;
5956 rsurface.svector3f = rsurface.array_deformedsvector3f;
5957 rsurface.svector3f_bufferobject = 0;
5958 rsurface.svector3f_bufferoffset = 0;
5959 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5960 rsurface.tvector3f_bufferobject = 0;
5961 rsurface.tvector3f_bufferoffset = 0;
5962 rsurface.normal3f = rsurface.array_deformednormal3f;
5963 rsurface.normal3f_bufferobject = 0;
5964 rsurface.normal3f_bufferoffset = 0;
5966 case Q3DEFORM_NORMAL:
5967 // deform the normals to make reflections wavey
5968 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5970 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5971 for (j = 0;j < surface->num_vertices;j++)
5974 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5975 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5976 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5977 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5978 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5979 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5980 VectorNormalize(normal);
5982 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 != 0);
5984 rsurface.svector3f = rsurface.array_deformedsvector3f;
5985 rsurface.svector3f_bufferobject = 0;
5986 rsurface.svector3f_bufferoffset = 0;
5987 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5988 rsurface.tvector3f_bufferobject = 0;
5989 rsurface.tvector3f_bufferoffset = 0;
5990 rsurface.normal3f = rsurface.array_deformednormal3f;
5991 rsurface.normal3f_bufferobject = 0;
5992 rsurface.normal3f_bufferoffset = 0;
5995 // deform vertex array to make wavey water and flags and such
5996 waveparms[0] = deform->waveparms[0];
5997 waveparms[1] = deform->waveparms[1];
5998 waveparms[2] = deform->waveparms[2];
5999 waveparms[3] = deform->waveparms[3];
6000 // this is how a divisor of vertex influence on deformation
6001 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6002 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6003 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6005 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6006 for (j = 0;j < surface->num_vertices;j++)
6008 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6009 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6010 // if the wavefunc depends on time, evaluate it per-vertex
6013 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6014 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6016 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6019 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6020 rsurface.vertex3f_bufferobject = 0;
6021 rsurface.vertex3f_bufferoffset = 0;
6023 case Q3DEFORM_BULGE:
6024 // deform vertex array to make the surface have moving bulges
6025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6027 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6028 for (j = 0;j < surface->num_vertices;j++)
6030 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6031 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6034 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6035 rsurface.vertex3f_bufferobject = 0;
6036 rsurface.vertex3f_bufferoffset = 0;
6039 // deform vertex array
6040 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6041 VectorScale(deform->parms, scale, waveparms);
6042 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6044 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6045 for (j = 0;j < surface->num_vertices;j++)
6046 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6048 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6049 rsurface.vertex3f_bufferobject = 0;
6050 rsurface.vertex3f_bufferoffset = 0;
6054 // generate texcoords based on the chosen texcoord source
6055 switch(rsurface.texture->tcgen.tcgen)
6058 case Q3TCGEN_TEXTURE:
6059 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6060 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6061 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6063 case Q3TCGEN_LIGHTMAP:
6064 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6065 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6066 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6068 case Q3TCGEN_VECTOR:
6069 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6071 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6072 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)
6074 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6075 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6078 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6079 rsurface.texcoordtexture2f_bufferobject = 0;
6080 rsurface.texcoordtexture2f_bufferoffset = 0;
6082 case Q3TCGEN_ENVIRONMENT:
6083 // make environment reflections using a spheremap
6084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6086 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6087 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6088 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6089 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6090 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6092 // identical to Q3A's method, but executed in worldspace so
6093 // carried models can be shiny too
6095 float viewer[3], d, reflected[3], worldreflected[3];
6097 VectorSubtract(rsurface.modelorg, vertex, viewer);
6098 // VectorNormalize(viewer);
6100 d = DotProduct(normal, viewer);
6102 reflected[0] = normal[0]*2*d - viewer[0];
6103 reflected[1] = normal[1]*2*d - viewer[1];
6104 reflected[2] = normal[2]*2*d - viewer[2];
6105 // note: this is proportinal to viewer, so we can normalize later
6107 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6108 VectorNormalize(worldreflected);
6110 // note: this sphere map only uses world x and z!
6111 // so positive and negative y will LOOK THE SAME.
6112 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6113 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6116 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6117 rsurface.texcoordtexture2f_bufferobject = 0;
6118 rsurface.texcoordtexture2f_bufferoffset = 0;
6121 // the only tcmod that needs software vertex processing is turbulent, so
6122 // check for it here and apply the changes if needed
6123 // and we only support that as the first one
6124 // (handling a mixture of turbulent and other tcmods would be problematic
6125 // without punting it entirely to a software path)
6126 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6128 amplitude = rsurface.texture->tcmods[0].parms[1];
6129 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6130 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6132 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6133 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)
6135 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6136 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6139 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6140 rsurface.texcoordtexture2f_bufferobject = 0;
6141 rsurface.texcoordtexture2f_bufferoffset = 0;
6143 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6144 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6145 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6146 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6149 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6152 const msurface_t *surface = texturesurfacelist[0];
6153 const msurface_t *surface2;
6158 // TODO: lock all array ranges before render, rather than on each surface
6159 if (texturenumsurfaces == 1)
6161 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6162 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);
6164 else if (r_batchmode.integer == 2)
6166 #define MAXBATCHTRIANGLES 4096
6167 int batchtriangles = 0;
6168 int batchelements[MAXBATCHTRIANGLES*3];
6169 for (i = 0;i < texturenumsurfaces;i = j)
6171 surface = texturesurfacelist[i];
6173 if (surface->num_triangles > MAXBATCHTRIANGLES)
6175 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);
6178 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6179 batchtriangles = surface->num_triangles;
6180 firstvertex = surface->num_firstvertex;
6181 endvertex = surface->num_firstvertex + surface->num_vertices;
6182 for (;j < texturenumsurfaces;j++)
6184 surface2 = texturesurfacelist[j];
6185 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6187 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6188 batchtriangles += surface2->num_triangles;
6189 firstvertex = min(firstvertex, surface2->num_firstvertex);
6190 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6192 surface2 = texturesurfacelist[j-1];
6193 numvertices = endvertex - firstvertex;
6194 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6197 else if (r_batchmode.integer == 1)
6199 for (i = 0;i < texturenumsurfaces;i = j)
6201 surface = texturesurfacelist[i];
6202 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6203 if (texturesurfacelist[j] != surface2)
6205 surface2 = texturesurfacelist[j-1];
6206 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6207 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6208 GL_LockArrays(surface->num_firstvertex, numvertices);
6209 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6214 for (i = 0;i < texturenumsurfaces;i++)
6216 surface = texturesurfacelist[i];
6217 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6218 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);
6223 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6225 int i, planeindex, vertexindex;
6229 r_waterstate_waterplane_t *p, *bestp;
6230 msurface_t *surface;
6231 if (r_waterstate.renderingscene)
6233 for (i = 0;i < texturenumsurfaces;i++)
6235 surface = texturesurfacelist[i];
6236 if (lightmaptexunit >= 0)
6237 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6238 if (deluxemaptexunit >= 0)
6239 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6240 // pick the closest matching water plane
6243 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6246 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6248 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6249 d += fabs(PlaneDiff(vert, &p->plane));
6251 if (bestd > d || !bestp)
6259 if (refractiontexunit >= 0)
6260 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6261 if (reflectiontexunit >= 0)
6262 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6266 if (refractiontexunit >= 0)
6267 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6268 if (reflectiontexunit >= 0)
6269 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6271 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6272 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);
6276 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6280 const msurface_t *surface = texturesurfacelist[0];
6281 const msurface_t *surface2;
6286 // TODO: lock all array ranges before render, rather than on each surface
6287 if (texturenumsurfaces == 1)
6289 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6290 if (deluxemaptexunit >= 0)
6291 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6292 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6293 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);
6295 else if (r_batchmode.integer == 2)
6297 #define MAXBATCHTRIANGLES 4096
6298 int batchtriangles = 0;
6299 int batchelements[MAXBATCHTRIANGLES*3];
6300 for (i = 0;i < texturenumsurfaces;i = j)
6302 surface = texturesurfacelist[i];
6303 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6304 if (deluxemaptexunit >= 0)
6305 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6307 if (surface->num_triangles > MAXBATCHTRIANGLES)
6309 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);
6312 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6313 batchtriangles = surface->num_triangles;
6314 firstvertex = surface->num_firstvertex;
6315 endvertex = surface->num_firstvertex + surface->num_vertices;
6316 for (;j < texturenumsurfaces;j++)
6318 surface2 = texturesurfacelist[j];
6319 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6321 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6322 batchtriangles += surface2->num_triangles;
6323 firstvertex = min(firstvertex, surface2->num_firstvertex);
6324 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6326 surface2 = texturesurfacelist[j-1];
6327 numvertices = endvertex - firstvertex;
6328 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6331 else if (r_batchmode.integer == 1)
6334 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6335 for (i = 0;i < texturenumsurfaces;i = j)
6337 surface = texturesurfacelist[i];
6338 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6339 if (texturesurfacelist[j] != surface2)
6341 Con_Printf(" %i", j - i);
6344 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6346 for (i = 0;i < texturenumsurfaces;i = j)
6348 surface = texturesurfacelist[i];
6349 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6350 if (deluxemaptexunit >= 0)
6351 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6352 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6353 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6356 Con_Printf(" %i", j - i);
6358 surface2 = texturesurfacelist[j-1];
6359 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6360 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6361 GL_LockArrays(surface->num_firstvertex, numvertices);
6362 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6370 for (i = 0;i < texturenumsurfaces;i++)
6372 surface = texturesurfacelist[i];
6373 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6374 if (deluxemaptexunit >= 0)
6375 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6376 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6377 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);
6382 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6385 int texturesurfaceindex;
6386 if (r_showsurfaces.integer == 2)
6388 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6390 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6391 for (j = 0;j < surface->num_triangles;j++)
6393 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6394 GL_Color(f, f, f, 1);
6395 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6401 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6403 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6404 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6405 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);
6406 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6407 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);
6412 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6414 int texturesurfaceindex;
6417 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6419 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6420 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)
6428 rsurface.lightmapcolor4f = rsurface.array_color4f;
6429 rsurface.lightmapcolor4f_bufferobject = 0;
6430 rsurface.lightmapcolor4f_bufferoffset = 0;
6433 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6435 int texturesurfaceindex;
6439 if (rsurface.lightmapcolor4f)
6441 // generate color arrays for the surfaces in this list
6442 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6444 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6445 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)
6447 f = FogPoint_Model(v);
6457 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6459 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6460 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)
6462 f = FogPoint_Model(v);
6470 rsurface.lightmapcolor4f = rsurface.array_color4f;
6471 rsurface.lightmapcolor4f_bufferobject = 0;
6472 rsurface.lightmapcolor4f_bufferoffset = 0;
6475 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6477 int texturesurfaceindex;
6481 if (!rsurface.lightmapcolor4f)
6483 // generate color arrays for the surfaces in this list
6484 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6487 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
6489 f = FogPoint_Model(v);
6490 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6491 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6492 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6496 rsurface.lightmapcolor4f = rsurface.array_color4f;
6497 rsurface.lightmapcolor4f_bufferobject = 0;
6498 rsurface.lightmapcolor4f_bufferoffset = 0;
6501 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6503 int texturesurfaceindex;
6506 if (!rsurface.lightmapcolor4f)
6508 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6510 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6511 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)
6519 rsurface.lightmapcolor4f = rsurface.array_color4f;
6520 rsurface.lightmapcolor4f_bufferobject = 0;
6521 rsurface.lightmapcolor4f_bufferoffset = 0;
6524 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6526 int texturesurfaceindex;
6529 if (!rsurface.lightmapcolor4f)
6531 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6533 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6534 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)
6536 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6537 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6538 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6542 rsurface.lightmapcolor4f = rsurface.array_color4f;
6543 rsurface.lightmapcolor4f_bufferobject = 0;
6544 rsurface.lightmapcolor4f_bufferoffset = 0;
6547 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6550 rsurface.lightmapcolor4f = NULL;
6551 rsurface.lightmapcolor4f_bufferobject = 0;
6552 rsurface.lightmapcolor4f_bufferoffset = 0;
6553 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6554 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6555 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6556 GL_Color(r, g, b, a);
6557 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6560 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6562 // TODO: optimize applyfog && applycolor case
6563 // just apply fog if necessary, and tint the fog color array if necessary
6564 rsurface.lightmapcolor4f = NULL;
6565 rsurface.lightmapcolor4f_bufferobject = 0;
6566 rsurface.lightmapcolor4f_bufferoffset = 0;
6567 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6568 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6569 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6570 GL_Color(r, g, b, a);
6571 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6574 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6576 int texturesurfaceindex;
6580 if (texturesurfacelist[0]->lightmapinfo)
6582 // generate color arrays for the surfaces in this list
6583 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6585 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6586 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6588 if (surface->lightmapinfo->samples)
6590 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6591 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6592 VectorScale(lm, scale, c);
6593 if (surface->lightmapinfo->styles[1] != 255)
6595 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6597 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6598 VectorMA(c, scale, lm, c);
6599 if (surface->lightmapinfo->styles[2] != 255)
6602 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6603 VectorMA(c, scale, lm, c);
6604 if (surface->lightmapinfo->styles[3] != 255)
6607 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6608 VectorMA(c, scale, lm, c);
6618 rsurface.lightmapcolor4f = rsurface.array_color4f;
6619 rsurface.lightmapcolor4f_bufferobject = 0;
6620 rsurface.lightmapcolor4f_bufferoffset = 0;
6624 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6625 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6626 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6628 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6629 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6630 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6631 GL_Color(r, g, b, a);
6632 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6635 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6637 int texturesurfaceindex;
6640 float *v, *c, *c2, alpha;
6641 vec3_t ambientcolor;
6642 vec3_t diffusecolor;
6646 VectorCopy(rsurface.modellight_lightdir, lightdir);
6647 f = 0.5f * r_refdef.lightmapintensity;
6648 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6649 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6650 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6651 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6652 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6653 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6655 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6657 // generate color arrays for the surfaces in this list
6658 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6660 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6661 int numverts = surface->num_vertices;
6662 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6663 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6664 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6665 // q3-style directional shading
6666 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6668 if ((f = DotProduct(c2, lightdir)) > 0)
6669 VectorMA(ambientcolor, f, diffusecolor, c);
6671 VectorCopy(ambientcolor, c);
6679 rsurface.lightmapcolor4f = rsurface.array_color4f;
6680 rsurface.lightmapcolor4f_bufferobject = 0;
6681 rsurface.lightmapcolor4f_bufferoffset = 0;
6682 *applycolor = false;
6686 *r = ambientcolor[0];
6687 *g = ambientcolor[1];
6688 *b = ambientcolor[2];
6689 rsurface.lightmapcolor4f = NULL;
6690 rsurface.lightmapcolor4f_bufferobject = 0;
6691 rsurface.lightmapcolor4f_bufferoffset = 0;
6695 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6697 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6698 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6699 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6700 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6701 GL_Color(r, g, b, a);
6702 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6705 void RSurf_SetupDepthAndCulling(void)
6707 // submodels are biased to avoid z-fighting with world surfaces that they
6708 // may be exactly overlapping (avoids z-fighting artifacts on certain
6709 // doors and things in Quake maps)
6710 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6711 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6712 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6713 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6716 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6718 // transparent sky would be ridiculous
6719 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6721 R_SetupGenericShader(false);
6724 skyrendernow = false;
6725 // we have to force off the water clipping plane while rendering sky
6729 // restore entity matrix
6730 R_Mesh_Matrix(&rsurface.matrix);
6732 RSurf_SetupDepthAndCulling();
6734 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6735 // skymasking on them, and Quake3 never did sky masking (unlike
6736 // software Quake and software Quake2), so disable the sky masking
6737 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6738 // and skymasking also looks very bad when noclipping outside the
6739 // level, so don't use it then either.
6740 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6742 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6743 R_Mesh_ColorPointer(NULL, 0, 0);
6744 R_Mesh_ResetTextureState();
6745 if (skyrendermasked)
6747 R_SetupDepthOrShadowShader();
6748 // depth-only (masking)
6749 GL_ColorMask(0,0,0,0);
6750 // just to make sure that braindead drivers don't draw
6751 // anything despite that colormask...
6752 GL_BlendFunc(GL_ZERO, GL_ONE);
6756 R_SetupGenericShader(false);
6758 GL_BlendFunc(GL_ONE, GL_ZERO);
6760 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6761 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6762 if (skyrendermasked)
6763 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6765 R_Mesh_ResetTextureState();
6766 GL_Color(1, 1, 1, 1);
6769 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6771 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6774 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6775 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6776 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6777 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6778 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6779 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6780 if (rsurface.texture->backgroundcurrentskinframe)
6782 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6783 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6784 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6785 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6787 if(rsurface.texture->colormapping)
6789 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6790 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6792 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6793 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6794 R_Mesh_ColorPointer(NULL, 0, 0);
6796 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6798 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6800 // render background
6801 GL_BlendFunc(GL_ONE, GL_ZERO);
6803 GL_AlphaTest(false);
6805 GL_Color(1, 1, 1, 1);
6806 R_Mesh_ColorPointer(NULL, 0, 0);
6808 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6809 if (r_glsl_permutation)
6811 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6812 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6813 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6814 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6815 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6816 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6817 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);
6819 GL_LockArrays(0, 0);
6821 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6822 GL_DepthMask(false);
6823 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6824 R_Mesh_ColorPointer(NULL, 0, 0);
6826 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6827 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6828 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6831 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6832 if (!r_glsl_permutation)
6835 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6836 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6837 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6838 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6839 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6840 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6842 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6844 GL_BlendFunc(GL_ONE, GL_ZERO);
6846 GL_AlphaTest(false);
6850 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6851 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6852 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6855 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6857 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6858 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);
6860 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6864 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6865 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);
6867 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6869 GL_LockArrays(0, 0);
6872 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6874 // OpenGL 1.3 path - anything not completely ancient
6875 int texturesurfaceindex;
6876 qboolean applycolor;
6880 const texturelayer_t *layer;
6881 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6883 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6886 int layertexrgbscale;
6887 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6889 if (layerindex == 0)
6893 GL_AlphaTest(false);
6894 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6897 GL_DepthMask(layer->depthmask && writedepth);
6898 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6899 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6901 layertexrgbscale = 4;
6902 VectorScale(layer->color, 0.25f, layercolor);
6904 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6906 layertexrgbscale = 2;
6907 VectorScale(layer->color, 0.5f, layercolor);
6911 layertexrgbscale = 1;
6912 VectorScale(layer->color, 1.0f, layercolor);
6914 layercolor[3] = layer->color[3];
6915 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6916 R_Mesh_ColorPointer(NULL, 0, 0);
6917 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6918 switch (layer->type)
6920 case TEXTURELAYERTYPE_LITTEXTURE:
6921 memset(&m, 0, sizeof(m));
6922 m.tex[0] = R_GetTexture(r_texture_white);
6923 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6924 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6925 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6926 m.tex[1] = R_GetTexture(layer->texture);
6927 m.texmatrix[1] = layer->texmatrix;
6928 m.texrgbscale[1] = layertexrgbscale;
6929 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6930 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6931 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6932 R_Mesh_TextureState(&m);
6933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6934 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6935 else if (rsurface.uselightmaptexture)
6936 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6938 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6940 case TEXTURELAYERTYPE_TEXTURE:
6941 memset(&m, 0, sizeof(m));
6942 m.tex[0] = R_GetTexture(layer->texture);
6943 m.texmatrix[0] = layer->texmatrix;
6944 m.texrgbscale[0] = layertexrgbscale;
6945 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6946 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6947 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6948 R_Mesh_TextureState(&m);
6949 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6951 case TEXTURELAYERTYPE_FOG:
6952 memset(&m, 0, sizeof(m));
6953 m.texrgbscale[0] = layertexrgbscale;
6956 m.tex[0] = R_GetTexture(layer->texture);
6957 m.texmatrix[0] = layer->texmatrix;
6958 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6959 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6960 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6962 R_Mesh_TextureState(&m);
6963 // generate a color array for the fog pass
6964 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6969 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6970 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)
6972 f = 1 - FogPoint_Model(v);
6973 c[0] = layercolor[0];
6974 c[1] = layercolor[1];
6975 c[2] = layercolor[2];
6976 c[3] = f * layercolor[3];
6979 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6982 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6984 GL_LockArrays(0, 0);
6987 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6989 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6990 GL_AlphaTest(false);
6994 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6996 // OpenGL 1.1 - crusty old voodoo path
6997 int texturesurfaceindex;
7001 const texturelayer_t *layer;
7002 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7004 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7006 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7008 if (layerindex == 0)
7012 GL_AlphaTest(false);
7013 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7016 GL_DepthMask(layer->depthmask && writedepth);
7017 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7018 R_Mesh_ColorPointer(NULL, 0, 0);
7019 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7020 switch (layer->type)
7022 case TEXTURELAYERTYPE_LITTEXTURE:
7023 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7025 // two-pass lit texture with 2x rgbscale
7026 // first the lightmap pass
7027 memset(&m, 0, sizeof(m));
7028 m.tex[0] = R_GetTexture(r_texture_white);
7029 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7030 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7031 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7032 R_Mesh_TextureState(&m);
7033 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7034 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7035 else if (rsurface.uselightmaptexture)
7036 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7038 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7039 GL_LockArrays(0, 0);
7040 // then apply the texture to it
7041 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7042 memset(&m, 0, sizeof(m));
7043 m.tex[0] = R_GetTexture(layer->texture);
7044 m.texmatrix[0] = layer->texmatrix;
7045 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7046 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7047 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7048 R_Mesh_TextureState(&m);
7049 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);
7053 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7054 memset(&m, 0, sizeof(m));
7055 m.tex[0] = R_GetTexture(layer->texture);
7056 m.texmatrix[0] = layer->texmatrix;
7057 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7058 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7059 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7060 R_Mesh_TextureState(&m);
7061 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7062 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);
7064 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);
7067 case TEXTURELAYERTYPE_TEXTURE:
7068 // singletexture unlit texture with transparency support
7069 memset(&m, 0, sizeof(m));
7070 m.tex[0] = R_GetTexture(layer->texture);
7071 m.texmatrix[0] = layer->texmatrix;
7072 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7073 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7074 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7075 R_Mesh_TextureState(&m);
7076 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);
7078 case TEXTURELAYERTYPE_FOG:
7079 // singletexture fogging
7080 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7083 memset(&m, 0, sizeof(m));
7084 m.tex[0] = R_GetTexture(layer->texture);
7085 m.texmatrix[0] = layer->texmatrix;
7086 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7087 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7088 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7089 R_Mesh_TextureState(&m);
7092 R_Mesh_ResetTextureState();
7093 // generate a color array for the fog pass
7094 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7098 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7099 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)
7101 f = 1 - FogPoint_Model(v);
7102 c[0] = layer->color[0];
7103 c[1] = layer->color[1];
7104 c[2] = layer->color[2];
7105 c[3] = f * layer->color[3];
7108 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7111 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7113 GL_LockArrays(0, 0);
7116 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7118 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7119 GL_AlphaTest(false);
7123 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7127 GL_AlphaTest(false);
7128 R_Mesh_ColorPointer(NULL, 0, 0);
7129 R_Mesh_ResetTextureState();
7130 R_SetupGenericShader(false);
7132 if(rsurface.texture && rsurface.texture->currentskinframe)
7134 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7135 c[3] *= rsurface.texture->currentalpha;
7145 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7147 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7148 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7149 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7152 // brighten it up (as texture value 127 means "unlit")
7153 c[0] *= 2 * r_refdef.view.colorscale;
7154 c[1] *= 2 * r_refdef.view.colorscale;
7155 c[2] *= 2 * r_refdef.view.colorscale;
7157 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7158 c[3] *= r_wateralpha.value;
7160 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7163 GL_DepthMask(false);
7165 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7167 GL_BlendFunc(GL_ONE, GL_ONE);
7168 GL_DepthMask(false);
7170 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7172 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7173 GL_DepthMask(false);
7175 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7177 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7178 GL_DepthMask(false);
7182 GL_BlendFunc(GL_ONE, GL_ZERO);
7183 GL_DepthMask(writedepth);
7186 rsurface.lightmapcolor4f = NULL;
7188 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7190 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7192 rsurface.lightmapcolor4f = NULL;
7193 rsurface.lightmapcolor4f_bufferobject = 0;
7194 rsurface.lightmapcolor4f_bufferoffset = 0;
7196 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7198 qboolean applycolor = true;
7201 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7203 r_refdef.lightmapintensity = 1;
7204 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7205 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7209 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7211 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7212 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7213 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7216 if(!rsurface.lightmapcolor4f)
7217 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7219 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7220 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7221 if(r_refdef.fogenabled)
7222 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7224 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7225 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7228 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7231 RSurf_SetupDepthAndCulling();
7232 if (r_showsurfaces.integer == 3)
7233 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7234 else if (r_glsl.integer && gl_support_fragment_shader)
7235 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7236 else if (gl_combine.integer && r_textureunits.integer >= 2)
7237 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7239 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7243 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7246 RSurf_SetupDepthAndCulling();
7247 if (r_showsurfaces.integer == 3)
7248 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7249 else if (r_glsl.integer && gl_support_fragment_shader)
7250 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7251 else if (gl_combine.integer && r_textureunits.integer >= 2)
7252 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7254 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7258 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7261 int texturenumsurfaces, endsurface;
7263 msurface_t *surface;
7264 msurface_t *texturesurfacelist[1024];
7266 // if the model is static it doesn't matter what value we give for
7267 // wantnormals and wanttangents, so this logic uses only rules applicable
7268 // to a model, knowing that they are meaningless otherwise
7269 if (ent == r_refdef.scene.worldentity)
7270 RSurf_ActiveWorldEntity();
7271 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7272 RSurf_ActiveModelEntity(ent, false, false);
7274 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7276 for (i = 0;i < numsurfaces;i = j)
7279 surface = rsurface.modelsurfaces + surfacelist[i];
7280 texture = surface->texture;
7281 rsurface.texture = R_GetCurrentTexture(texture);
7282 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7283 // scan ahead until we find a different texture
7284 endsurface = min(i + 1024, numsurfaces);
7285 texturenumsurfaces = 0;
7286 texturesurfacelist[texturenumsurfaces++] = surface;
7287 for (;j < endsurface;j++)
7289 surface = rsurface.modelsurfaces + surfacelist[j];
7290 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7292 texturesurfacelist[texturenumsurfaces++] = surface;
7294 // render the range of surfaces
7295 if (ent == r_refdef.scene.worldentity)
7296 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7298 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7300 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7301 GL_AlphaTest(false);
7304 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7306 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7310 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7312 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7314 RSurf_SetupDepthAndCulling();
7315 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7316 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7318 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7320 RSurf_SetupDepthAndCulling();
7321 GL_AlphaTest(false);
7322 R_Mesh_ColorPointer(NULL, 0, 0);
7323 R_Mesh_ResetTextureState();
7324 R_SetupGenericShader(false);
7325 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7327 GL_BlendFunc(GL_ONE, GL_ZERO);
7328 GL_Color(0, 0, 0, 1);
7329 GL_DepthTest(writedepth);
7330 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7332 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7334 RSurf_SetupDepthAndCulling();
7335 GL_AlphaTest(false);
7336 R_Mesh_ColorPointer(NULL, 0, 0);
7337 R_Mesh_ResetTextureState();
7338 R_SetupGenericShader(false);
7339 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7341 GL_BlendFunc(GL_ONE, GL_ZERO);
7343 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7345 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7346 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7347 else if (!rsurface.texture->currentnumlayers)
7349 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7351 // transparent surfaces get pushed off into the transparent queue
7352 int surfacelistindex;
7353 const msurface_t *surface;
7354 vec3_t tempcenter, center;
7355 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7357 surface = texturesurfacelist[surfacelistindex];
7358 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7359 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7360 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7361 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7362 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7367 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7368 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7373 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7377 // break the surface list down into batches by texture and use of lightmapping
7378 for (i = 0;i < numsurfaces;i = j)
7381 // texture is the base texture pointer, rsurface.texture is the
7382 // current frame/skin the texture is directing us to use (for example
7383 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7384 // use skin 1 instead)
7385 texture = surfacelist[i]->texture;
7386 rsurface.texture = R_GetCurrentTexture(texture);
7387 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7388 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7390 // if this texture is not the kind we want, skip ahead to the next one
7391 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7395 // simply scan ahead until we find a different texture or lightmap state
7396 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7398 // render the range of surfaces
7399 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7403 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7408 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7410 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7412 RSurf_SetupDepthAndCulling();
7413 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7414 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7416 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7418 RSurf_SetupDepthAndCulling();
7419 GL_AlphaTest(false);
7420 R_Mesh_ColorPointer(NULL, 0, 0);
7421 R_Mesh_ResetTextureState();
7422 R_SetupGenericShader(false);
7423 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7425 GL_BlendFunc(GL_ONE, GL_ZERO);
7426 GL_Color(0, 0, 0, 1);
7427 GL_DepthTest(writedepth);
7428 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7430 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7432 RSurf_SetupDepthAndCulling();
7433 GL_AlphaTest(false);
7434 R_Mesh_ColorPointer(NULL, 0, 0);
7435 R_Mesh_ResetTextureState();
7436 R_SetupGenericShader(false);
7437 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7439 GL_BlendFunc(GL_ONE, GL_ZERO);
7441 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7443 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7444 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7445 else if (!rsurface.texture->currentnumlayers)
7447 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7449 // transparent surfaces get pushed off into the transparent queue
7450 int surfacelistindex;
7451 const msurface_t *surface;
7452 vec3_t tempcenter, center;
7453 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7455 surface = texturesurfacelist[surfacelistindex];
7456 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7457 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7458 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7459 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7460 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7465 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7466 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7471 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7475 // break the surface list down into batches by texture and use of lightmapping
7476 for (i = 0;i < numsurfaces;i = j)
7479 // texture is the base texture pointer, rsurface.texture is the
7480 // current frame/skin the texture is directing us to use (for example
7481 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7482 // use skin 1 instead)
7483 texture = surfacelist[i]->texture;
7484 rsurface.texture = R_GetCurrentTexture(texture);
7485 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7486 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7488 // if this texture is not the kind we want, skip ahead to the next one
7489 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7493 // simply scan ahead until we find a different texture or lightmap state
7494 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7496 // render the range of surfaces
7497 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7501 float locboxvertex3f[6*4*3] =
7503 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7504 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7505 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7506 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7507 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7508 1,0,0, 0,0,0, 0,1,0, 1,1,0
7511 unsigned short locboxelements[6*2*3] =
7521 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7524 cl_locnode_t *loc = (cl_locnode_t *)ent;
7526 float vertex3f[6*4*3];
7528 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7529 GL_DepthMask(false);
7530 GL_DepthRange(0, 1);
7531 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7533 GL_CullFace(GL_NONE);
7534 R_Mesh_Matrix(&identitymatrix);
7536 R_Mesh_VertexPointer(vertex3f, 0, 0);
7537 R_Mesh_ColorPointer(NULL, 0, 0);
7538 R_Mesh_ResetTextureState();
7539 R_SetupGenericShader(false);
7542 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7543 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7544 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7545 surfacelist[0] < 0 ? 0.5f : 0.125f);
7547 if (VectorCompare(loc->mins, loc->maxs))
7549 VectorSet(size, 2, 2, 2);
7550 VectorMA(loc->mins, -0.5f, size, mins);
7554 VectorCopy(loc->mins, mins);
7555 VectorSubtract(loc->maxs, loc->mins, size);
7558 for (i = 0;i < 6*4*3;)
7559 for (j = 0;j < 3;j++, i++)
7560 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7562 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7565 void R_DrawLocs(void)
7568 cl_locnode_t *loc, *nearestloc;
7570 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7571 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7573 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7574 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7578 void R_DrawDebugModel(entity_render_t *ent)
7580 int i, j, k, l, flagsmask;
7581 const int *elements;
7583 msurface_t *surface;
7584 dp_model_t *model = ent->model;
7587 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7589 R_Mesh_ColorPointer(NULL, 0, 0);
7590 R_Mesh_ResetTextureState();
7591 R_SetupGenericShader(false);
7592 GL_DepthRange(0, 1);
7593 GL_DepthTest(!r_showdisabledepthtest.integer);
7594 GL_DepthMask(false);
7595 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7597 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7599 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7600 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7602 if (brush->colbrushf && brush->colbrushf->numtriangles)
7604 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7605 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);
7606 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7609 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7611 if (surface->num_collisiontriangles)
7613 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7614 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);
7615 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7620 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7622 if (r_showtris.integer || r_shownormals.integer)
7624 if (r_showdisabledepthtest.integer)
7626 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7627 GL_DepthMask(false);
7631 GL_BlendFunc(GL_ONE, GL_ZERO);
7634 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7636 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7638 rsurface.texture = R_GetCurrentTexture(surface->texture);
7639 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7641 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7642 if (r_showtris.value > 0)
7644 if (!rsurface.texture->currentlayers->depthmask)
7645 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7646 else if (ent == r_refdef.scene.worldentity)
7647 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7649 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7650 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7651 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7652 R_Mesh_ColorPointer(NULL, 0, 0);
7653 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7654 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7655 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7656 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);
7657 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7660 if (r_shownormals.value < 0)
7663 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7665 VectorCopy(rsurface.vertex3f + l * 3, v);
7666 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7667 qglVertex3f(v[0], v[1], v[2]);
7668 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7669 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7670 qglVertex3f(v[0], v[1], v[2]);
7675 if (r_shownormals.value > 0)
7678 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7680 VectorCopy(rsurface.vertex3f + l * 3, v);
7681 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7682 qglVertex3f(v[0], v[1], v[2]);
7683 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7684 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7685 qglVertex3f(v[0], v[1], v[2]);
7690 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7692 VectorCopy(rsurface.vertex3f + l * 3, v);
7693 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7694 qglVertex3f(v[0], v[1], v[2]);
7695 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7696 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7697 qglVertex3f(v[0], v[1], v[2]);
7702 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7704 VectorCopy(rsurface.vertex3f + l * 3, v);
7705 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7706 qglVertex3f(v[0], v[1], v[2]);
7707 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7708 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7709 qglVertex3f(v[0], v[1], v[2]);
7716 rsurface.texture = NULL;
7720 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7721 int r_maxsurfacelist = 0;
7722 msurface_t **r_surfacelist = NULL;
7723 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7725 int i, j, endj, f, flagsmask;
7727 dp_model_t *model = r_refdef.scene.worldmodel;
7728 msurface_t *surfaces;
7729 unsigned char *update;
7730 int numsurfacelist = 0;
7734 if (r_maxsurfacelist < model->num_surfaces)
7736 r_maxsurfacelist = model->num_surfaces;
7738 Mem_Free(r_surfacelist);
7739 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7742 RSurf_ActiveWorldEntity();
7744 surfaces = model->data_surfaces;
7745 update = model->brushq1.lightmapupdateflags;
7747 // update light styles on this submodel
7748 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7750 model_brush_lightstyleinfo_t *style;
7751 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7753 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7755 int *list = style->surfacelist;
7756 style->value = r_refdef.scene.lightstylevalue[style->style];
7757 for (j = 0;j < style->numsurfaces;j++)
7758 update[list[j]] = true;
7763 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7767 R_DrawDebugModel(r_refdef.scene.worldentity);
7768 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7774 rsurface.uselightmaptexture = false;
7775 rsurface.texture = NULL;
7776 rsurface.rtlight = NULL;
7778 // add visible surfaces to draw list
7779 for (i = 0;i < model->nummodelsurfaces;i++)
7781 j = model->sortedmodelsurfaces[i];
7782 if (r_refdef.viewcache.world_surfacevisible[j])
7783 r_surfacelist[numsurfacelist++] = surfaces + j;
7785 // update lightmaps if needed
7787 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7788 if (r_refdef.viewcache.world_surfacevisible[j])
7790 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7791 // don't do anything if there were no surfaces
7792 if (!numsurfacelist)
7794 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7797 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7798 GL_AlphaTest(false);
7800 // add to stats if desired
7801 if (r_speeds.integer && !skysurfaces && !depthonly)
7803 r_refdef.stats.world_surfaces += numsurfacelist;
7804 for (j = 0;j < numsurfacelist;j++)
7805 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7807 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7810 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7812 int i, j, endj, f, flagsmask;
7814 dp_model_t *model = ent->model;
7815 msurface_t *surfaces;
7816 unsigned char *update;
7817 int numsurfacelist = 0;
7821 if (r_maxsurfacelist < model->num_surfaces)
7823 r_maxsurfacelist = model->num_surfaces;
7825 Mem_Free(r_surfacelist);
7826 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7829 // if the model is static it doesn't matter what value we give for
7830 // wantnormals and wanttangents, so this logic uses only rules applicable
7831 // to a model, knowing that they are meaningless otherwise
7832 if (ent == r_refdef.scene.worldentity)
7833 RSurf_ActiveWorldEntity();
7834 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7835 RSurf_ActiveModelEntity(ent, false, false);
7837 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7839 surfaces = model->data_surfaces;
7840 update = model->brushq1.lightmapupdateflags;
7842 // update light styles
7843 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7845 model_brush_lightstyleinfo_t *style;
7846 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7848 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7850 int *list = style->surfacelist;
7851 style->value = r_refdef.scene.lightstylevalue[style->style];
7852 for (j = 0;j < style->numsurfaces;j++)
7853 update[list[j]] = true;
7858 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7862 R_DrawDebugModel(ent);
7863 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7869 rsurface.uselightmaptexture = false;
7870 rsurface.texture = NULL;
7871 rsurface.rtlight = NULL;
7873 // add visible surfaces to draw list
7874 for (i = 0;i < model->nummodelsurfaces;i++)
7875 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7876 // don't do anything if there were no surfaces
7877 if (!numsurfacelist)
7879 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7882 // update lightmaps if needed
7884 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7886 R_BuildLightMap(ent, surfaces + j);
7887 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7888 GL_AlphaTest(false);
7890 // add to stats if desired
7891 if (r_speeds.integer && !skysurfaces && !depthonly)
7893 r_refdef.stats.entities_surfaces += numsurfacelist;
7894 for (j = 0;j < numsurfacelist;j++)
7895 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7897 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity